Leaked source code of windows server 2003
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.
 
 
 
 
 
 

4569 lines
148 KiB

/*******************************************************************************
*
* admindoc.cpp
*
* implementation of the CWinAdminDoc class
*
* copyright notice: Copyright 1997, Citrix Systems Inc.
* Copyright (c) 1998 - 1999 Microsoft Corporation
*
* $Author: donm $ Don Messerli
*
* $Log: N:\nt\private\utils\citrix\winutils\tsadmin\VCS\admindoc.cpp $
*
* Rev 1.15 25 Apr 1998 13:43:08 donm
* MS 2167: try to use proper Wd from registry
*
* Rev 1.14 19 Feb 1998 17:39:28 donm
* removed latest extension DLL support
*
* Rev 1.12 19 Jan 1998 16:45:28 donm
* new ui behavior for domains and servers
*
* Rev 1.11 13 Nov 1997 13:18:46 donm
* removed check for ICA for shadowing
*
* Rev 1.10 07 Nov 1997 23:05:58 donm
* fixed inability to logoff/reset
* Rev 1.0 30 Jul 1997 17:10:10 butchd
* Initial revision.
*
*******************************************************************************/
#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
#ifdef _STRESS_BUILD
extern BOOL g_fWaitForAllServersToDisconnect;
#endif
DWORD Shadow_WarningProc( LPVOID param );
INT_PTR CALLBACK ShadowWarn_WndProc( HWND , UINT , WPARAM , LPARAM );
void CenterDlg(HWND hwndToCenterOn , HWND hDlg );
HWND g_hwndShadowWarn = NULL;
DWORD g_dwTreeViewExpandedStates;
// Initialize static variable
NODETYPE CWinAdminDoc::gm_CurrentSelType = NODE_NONE;
#define WM_SETTHEEVENT ( WM_USER + 755 )
// Sort order for Connect States
ULONG SortOrder[] =
{
3, //State_Active user logged on to WinStation
2, //State_Connected WinStation connected to client
0, //State_ConnectQuery in the process of connecting to client
5, //State_Shadow shadowing another WinStation
4, //State_Disconnected WinStation logged on without client
6, //State_Idle waiting for client to connect
1, //State_Listen WinStation is listening for connection
9, //State_Reset WinStation is being reset
7, //State_Down WinStation is down due to error
8 //State_Init WinStation in initialization
};
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc
IMPLEMENT_DYNCREATE(CWinAdminDoc, CDocument)
BEGIN_MESSAGE_MAP(CWinAdminDoc, CDocument)
//{{AFX_MSG_MAP(CWinAdminDoc)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CWinAdminDoc::m_ProcessContinue = TRUE;
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc constructor
//
CWinAdminDoc::CWinAdminDoc()
{
// TODO: add one-time construction code here
m_CurrentSelectedNode = NULL;
m_CurrentSelectedType = NODE_NONE;
m_pTempSelectedNode = NULL;
m_TempSelectedType = NODE_NONE;
m_AllViewsReady = FALSE;
m_hProcessThread = NULL;
m_pCurrentDomain = NULL;
m_pCurrentServer = NULL;
m_pPersistentConnections = NULL;
m_InRefresh = FALSE;
m_bInShutdown = FALSE;
m_UnknownString = ::GetUnknownString();
ASSERT( m_UnknownString != NULL );
((CWinAdminApp*)AfxGetApp())->SetDocument(this);
// If there is an extension DLL, get a pointer to it's global
// info structure
LPFNEXGETGLOBALINFOPROC InfoProc = ((CWinAdminApp*)AfxGetApp())->GetExtGetGlobalInfoProc();
if(InfoProc)
{
m_pExtGlobalInfo = (*InfoProc)();
}
else
{
m_pExtGlobalInfo = NULL;
}
// create the default extended server info
// for servers that haven't had their extended info
// created yet
m_pDefaultExtServerInfo = new ExtServerInfo;
CString NAString;
NAString.LoadString(IDS_NOT_APPLICABLE);
memset(m_pDefaultExtServerInfo, 0, sizeof(ExtServerInfo));
// This is so the N/A TcpAddresses will sort at the end
m_pDefaultExtServerInfo->RawTcpAddress = 0xFFFFFFFF;
m_pDefaultExtServerInfo->ServerTotalInUse = 0xFFFFFFFF;
lstrcpyn(m_pDefaultExtServerInfo->TcpAddress, NAString, sizeof(m_pDefaultExtServerInfo->TcpAddress) / sizeof(TCHAR));
lstrcpyn(m_pDefaultExtServerInfo->IpxAddress, NAString, sizeof(m_pDefaultExtServerInfo->IpxAddress) / sizeof(TCHAR));
m_focusstate = TREE_VIEW;
m_prevFocusState = TAB_CTRL;
m_fOnTab = FALSE;
m_pszFavList = NULL;
} // end CWinAdminDoc::CWinAdminDoc
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc destructor
//
CWinAdminDoc::~CWinAdminDoc()
{
// all code moved to Shutdown();
delete m_pDefaultExtServerInfo;
if(m_pPersistentConnections) LocalFree(m_pPersistentConnections);
if( m_UnknownString != NULL )
{
LocalFree( ( PVOID )m_UnknownString );
}
} // end CWinAdminDoc::~CWinAdminDoc
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::ShutdownMessage
//
void CWinAdminDoc::ShutdownMessage(UINT id, CDialog *pDlg)
{
ASSERT(pDlg);
CString AString;
AString.LoadString(id);
pDlg->SetDlgItemText(IDC_SHUTDOWN_MSG, AString);
} // end CWinAdminDoc::ShutdownMessage
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::Shutdown
//
void CWinAdminDoc::Shutdown(CDialog *pDlg)
{
ASSERT(pDlg);
m_bInShutdown = TRUE;
// Iterate through the domain list
POSITION pos = m_DomainList.GetHeadPosition();
ShutdownMessage(IDS_SHUTDOWN_DOMAINTHREADS, pDlg);
while(pos) {
// Go to the next domain in the list
CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
pDomain->ClearBackgroundContinue();
// Fire off the event to wake him up if he is
// waiting
pDomain->SetEnumEvent();
}
pos = m_DomainList.GetHeadPosition();
while(pos) {
// Go to the next domain in the list
CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
pDomain->StopEnumerating();
}
// Tell the process thread to terminate and wait for it to do so
// make sure the process thread is still running first
DWORD dwThreadExitCode;
GetExitCodeThread(m_hProcessThread, &dwThreadExitCode);
if (dwThreadExitCode == STILL_ACTIVE)
{
ShutdownMessage(IDS_SHUTDOWN_PROCTHREAD, pDlg);
m_ProcessContinue = FALSE;
// fire off the event to wake him up if he is waiting
m_ProcessWakeUpEvent.SetEvent();
// wait until the thread is finished
WaitForSingleObject(m_hProcessThread, INFINITE);
// we're done with our process thread so we can close the handle
CloseHandle(m_hProcessThread);
}
ShutdownMessage(IDS_SHUTDOWN_PREFS, pDlg);
WritePreferences();
LockServerList();
ShutdownMessage(IDS_SHUTDOWN_NOTIFY, pDlg);
// First, tell all the server background threads to stop.
// We do this before the destructor for each server does it
// so that the background threads for all the servers can stop
// and we don't have to wait until we get to the destructor for
// each server
pos = m_ServerList.GetHeadPosition();
while(pos)
{
// Go to the next server in the list
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
pServer->ClearBackgroundContinue();
}
// Iterate through the server list
pos = m_ServerList.GetHeadPosition();
while(pos) {
// Go to the next server in the list
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if(pServer->IsState(SS_GOOD)) {
CString AString;
AString.Format(IDS_DISCONNECTING, pServer->GetName());
pDlg->SetDlgItemText(IDC_SHUTDOWN_MSG, AString);
}
pServer->Disconnect( );
delete pServer;
}
m_ServerList.RemoveAll();
UnlockServerList();
// Iterate through the domain list
pos = m_DomainList.GetHeadPosition();
while(pos) {
// Go to the next domain in the list
CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
delete pDomain;
}
m_DomainList.RemoveAll();
// If there is an extension DLL, call it's shutdown function
LPFNEXSHUTDOWNPROC ShutdownProc = ((CWinAdminApp*)AfxGetApp())->GetExtShutdownProc();
if(ShutdownProc) {
(*ShutdownProc)();
}
// Iterate through the Wd list
LockWdList();
pos = m_WdList.GetHeadPosition();
while(pos) {
// Go to the next Wd in the list
CWd *pWd = (CWd*)m_WdList.GetNext(pos);
delete pWd;
}
m_WdList.RemoveAll();
UnlockWdList();
ShutdownMessage(IDS_DONE, pDlg);
} // end CWinAdminDoc::Shutdown
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanCloseFrame
//
BOOL CWinAdminDoc::CanCloseFrame(CFrameWnd *pFW)
{
ASSERT(pFW);
CWaitCursor Nikki;
CDialog dlgWait;
dlgWait.Create(IDD_SHUTDOWN, pFW);
Shutdown(&dlgWait);
dlgWait.PostMessage(WM_CLOSE);
return TRUE;
} // end CWinAdminDoc::CanCloseFrame
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::OnNewDocument
//
BOOL CWinAdminDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
ReadPreferences();
BuildWdList();
BuildDomainList();
// Create a pServer object for the Server we are running on, this will give
// him a headstart in getting his information
CServer *pServer = new CServer(m_pCurrentDomain, ((CWinAdminApp*)AfxGetApp())->GetCurrentServerName(), FALSE, TRUE);
m_pCurrentServer = pServer;
if( pServer )
{
AddServer(pServer);
}
// Start enumerating servers in the current domain
// if(m_pCurrentDomain) m_pCurrentDomain->StartEnumerating();
// Start the background thread to enumerate processes
DWORD dwThreadID;
m_hProcessThread = CreateThread(NULL, // default security attributes
0, // default stack size
CWinAdminDoc::ProcessThreadProc,
this, // param passed into threadProc
0, // default creation flags
&dwThreadID);
// make sure our thread created by ensuring the handle is non null
if (!m_hProcessThread)
{
return FALSE;
}
return TRUE;
} // end CWinAdminDoc::OnNewDocument
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc serialization
//
void CWinAdminDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
} // end CWinAdminDoc::Serialize
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc diagnostics
//
#ifdef _DEBUG
void CWinAdminDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CWinAdminDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::ShouldConnect
//
// Returns TRUE if the server is in the list of persistent connections
//
BOOL CWinAdminDoc::ShouldConnect(LPWSTR pServerName)
{
ASSERT(pServerName);
if(m_ConnectionsPersistent && m_pPersistentConnections)
{
LPWSTR pTemp = m_pPersistentConnections;
while(*pTemp)
{
if( !wcscmp( pTemp , pServerName ) )
{
return TRUE;
}
// Go to the next server in the buffer
pTemp += (wcslen(pTemp) + 1);
}
}
return FALSE;
}
//=-------------------------------------------------------------------
BOOL CWinAdminDoc::ShouldAddToFav( LPTSTR pServerName )
{
ODS( L"CWinAdminDoc::ShouldAddToFav\n" );
if( m_pszFavList != NULL )
{
LPTSTR pszTemp = m_pszFavList;
while(*pszTemp)
{
if( !wcscmp( pszTemp , pServerName ) )
{
DBGMSG( L"Adding %s to favorites\n" , pszTemp );
return TRUE;
}
// Go to the next server in the buffer
pszTemp += ( wcslen( pszTemp ) + 1 );
}
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::ProcessThreadProc
//
// Static member function for process thread
// Called with AfxBeginThread
// Thread terminates when function returns
//
DWORD WINAPI CWinAdminDoc::ProcessThreadProc(LPVOID _doc)
{
ASSERT(_doc);
// We need a pointer to the document so we can make
// calls to member functions
CWinAdminDoc *pDoc = (CWinAdminDoc*)_doc;
// We can't send messages to the view until they're ready
while(!pDoc->AreAllViewsReady()) Sleep(500);
pDoc->AddToFavoritesNow( );
CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
if( p != NULL )
{
p->SendMessage( WM_ADMIN_UPDATE_TVSTATE , 0 , 0 );
}
while(1) {
// We don't want to do this constantly, it eats up processor cycles
// Document destructor will signal the event to wake us up if he
// wants us to quit
pDoc->m_ProcessWakeUpEvent.Lock(((CWinAdminApp*)AfxGetApp())->GetProcessListRefreshTime());
// Make sure we don't have to quit
if(!ShouldProcessContinue()) return 0;
// We only want to enumerate processes if the page is VIEW_SERVER or VIEW_WINSTATION
if(pDoc->GetCurrentView() == VIEW_SERVER || pDoc->GetCurrentView() == VIEW_WINSTATION) {
CServer *pServer = (pDoc->GetCurrentView() == VIEW_SERVER) ? (CServer*)pDoc->GetCurrentSelectedNode()
: (CServer*)((CWinStation*)pDoc->GetCurrentSelectedNode())->GetServer();
// Enumerate processes for this server if his state is SS_GOOD
if(pServer->IsState(SS_GOOD)) {
pServer->EnumerateProcesses();
}
// Make sure we don't have to quit
if(!ShouldProcessContinue()) return 0;
// We only want to send a message to update the view if the
// view is still VEIW_SERVER/VIEW_WINSTATION and the currently
// selected Server is the same one that we just enumerate processes for
if((pDoc->GetCurrentView() == VIEW_SERVER && pServer == (CServer*)pDoc->GetCurrentSelectedNode())
|| (pDoc->GetCurrentView() == VIEW_WINSTATION && pServer == (CServer*)((CWinStation*)pDoc->GetCurrentSelectedNode())->GetServer())) {
CFrameWnd *pWnd = (CFrameWnd*)pDoc->GetMainWnd();
if(pWnd && ::IsWindow(pWnd->GetSafeHwnd())) pWnd->SendMessage(WM_ADMIN_UPDATE_PROCESSES, 0, (LPARAM)pServer);
}
}
// Make sure we don't have to quit
if(!ShouldProcessContinue()) return 0;
}
return 0;
} // end CWinAdminDoc::ProcessThreadProc
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::UpdateAllProcesses
//
void CWinAdminDoc::UpdateAllProcesses()
{
LockServerList();
POSITION pos = m_ServerList.GetHeadPosition();
while(pos) {
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
// Enumerate processes for this server if his state is SS_GOOD
if(pServer->IsState(SS_GOOD)) {
pServer->EnumerateProcesses();
// Send a message to the view to update this server's processes
CFrameWnd *p = (CFrameWnd*)GetMainWnd();
if(p && ::IsWindow(p->GetSafeHwnd())) p->SendMessage(WM_ADMIN_UPDATE_PROCESSES, 0, (LPARAM)pServer);
}
}
UnlockServerList();
} // end CWinAdminDoc::UpdateAllProcesses
static TCHAR szWinAdminAppKey[] = REG_SOFTWARE_TSERVER TEXT("\\TSADMIN");
static TCHAR szConnectionsPersistent[] = TEXT("ConnectionsPersistent");
static TCHAR szFavList[] = TEXT("Favorites" );
static TCHAR szTVStates[] = TEXT( "TreeViewStates" );
static TCHAR szConnections[] = TEXT("Connections");
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::ReadPreferences
//
// Read user preferences
//
void CWinAdminDoc::ReadPreferences()
{
HKEY hKeyWinAdmin;
DWORD dwType, cbData, dwValue;
// Set to defaults
m_ConnectionsPersistent = FALSE;
// Open registry key for our application
DWORD Disposition;
if( RegCreateKeyEx( HKEY_CURRENT_USER ,
szWinAdminAppKey,
0,
TEXT(""),
REG_OPTION_NON_VOLATILE,
KEY_READ,
NULL,
&hKeyWinAdmin,
&Disposition) != ERROR_SUCCESS )
{
return;
}
// Read the favorites list
DWORD dwLen = 0;
dwType = 0;
// See how big the multi-string is
int err = RegQueryValueEx( hKeyWinAdmin,
szFavList,
NULL,
&dwType,
NULL,
&dwLen );
if( err == ERROR_SUCCESS || err == ERROR_BUFFER_OVERFLOW )
{
m_pszFavList = ( LPWSTR )LocalAlloc( 0 , dwLen );
if( m_pszFavList != NULL )
{
memset( m_pszFavList , 0 , dwLen );
RegQueryValueEx( hKeyWinAdmin,
szFavList,
NULL,
&dwType,
(LPBYTE)m_pszFavList,
&dwLen);
}
}
// Read the Connections Persist preference
cbData = sizeof( m_ConnectionsPersistent );
if( RegQueryValueEx( hKeyWinAdmin ,
szConnectionsPersistent ,
NULL,
&dwType,
(LPBYTE)&dwValue,
&cbData) == ERROR_SUCCESS)
{
m_ConnectionsPersistent = dwValue;
}
// If connections are persistent, read the list of connections saved
if( m_ConnectionsPersistent )
{
dwLen = 0;
dwType = 0;
// See how big the multi-string is
err = RegQueryValueEx( hKeyWinAdmin,
szConnections,
NULL,
&dwType,
NULL,
&dwLen );
if(err && (err != ERROR_BUFFER_OVERFLOW) )
{
RegCloseKey(hKeyWinAdmin);
return;
}
m_pPersistentConnections = (LPWSTR)LocalAlloc(0, dwLen);
if( m_pPersistentConnections != NULL )
{
memset(m_pPersistentConnections, 0, dwLen);
RegQueryValueEx( hKeyWinAdmin,
szConnections,
NULL,
&dwType,
(LPBYTE)m_pPersistentConnections,
&dwLen);
}
}
g_dwTreeViewExpandedStates = 0;
dwLen = sizeof( g_dwTreeViewExpandedStates );
RegQueryValueEx( hKeyWinAdmin ,
szTVStates,
NULL,
&dwType,
( LPBYTE )&g_dwTreeViewExpandedStates,
&dwLen );
RegCloseKey(hKeyWinAdmin);
} // end CWinAdminDoc::ReadPreferences
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::WritePreferences
//
// Write user preferences
//
void CWinAdminDoc::WritePreferences()
{
HKEY hKeyWinAdmin;
DWORD dwValue;
// Open registry key for our application
DWORD Disposition;
if( RegCreateKeyEx( HKEY_CURRENT_USER,
szWinAdminAppKey,
0,
TEXT(""),
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKeyWinAdmin,
&Disposition) != ERROR_SUCCESS )
{
return;
}
// Write the servers that are in the favorite list
DWORD dwByteCount = 0;
LockServerList();
POSITION pos = m_ServerList.GetHeadPosition();
#ifdef _STRESS_BUILD
int nStressServerLimit = 0;
#endif;
while(pos)
{
#ifdef _STRESS_BUILD
if( nStressServerLimit >= 10000 )
{
break;
}
nStressServerLimit++;
#endif
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if( pServer->GetTreeItemFromFav( ) != NULL )
{
// format is domain/server
if( pServer->GetDomain( ) )
{
dwByteCount += ( wcslen( pServer->GetDomain( )->GetName() ) * 2 );
dwByteCount += 2;
}
dwByteCount += ( wcslen( pServer->GetName() ) + 1) * 2;
}
}
LPWSTR pBuffer = NULL;
if( dwByteCount != 0 )
{
dwByteCount += 2; // for ending null
// Allocate memory.
if( ( pBuffer = ( LPWSTR )LocalAlloc( LPTR, dwByteCount ) ) != NULL )
{
// Traverse list again and copy servers to buffer.
LPWSTR pTemp = pBuffer;
pos = m_ServerList.GetHeadPosition();
#ifdef _STRESS_BUILD
nStressServerLimit = 0;
#endif
while(pos)
{
#ifdef _STRESS_BUILD
if( nStressServerLimit >= 10000 )
{
break;
}
nStressServerLimit++;
#endif
// Go to the next server in the list
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if( pServer->GetTreeItemFromFav( ) != NULL )
{
if( pServer->GetDomain( ) )
{
lstrcpy( pTemp , pServer->GetDomain( )->GetName( ) );
lstrcat( pTemp , L"/" );
}
lstrcat(pTemp, pServer->GetName());
pTemp += ( wcslen( pTemp ) + 1);
}
}
*pTemp = L'\0'; // ending null
RegSetValueEx (hKeyWinAdmin, szFavList, 0, REG_MULTI_SZ, (PBYTE)pBuffer, dwByteCount);
LocalFree(pBuffer);
}
}
else
{
RegDeleteValue( hKeyWinAdmin , szFavList );
}
UnlockServerList();
// Write the persistent connections preference
dwValue = m_ConnectionsPersistent;
RegSetValueEx( hKeyWinAdmin,
szConnectionsPersistent,
0,
REG_DWORD,
(LPBYTE)&dwValue,
sizeof(DWORD)
);
if( m_ConnectionsPersistent )
{
// Create a multistring of the persistent connections
// loop through the list of servers and see how much memory
// to allocate for the multistring.
dwByteCount = 0;
LockServerList();
pos = m_ServerList.GetHeadPosition();
while(pos)
{
// Go to the next server in the list
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if( pServer->IsState(SS_GOOD) )
{
dwByteCount += (wcslen(pServer->GetName()) + 1) * 2;
}
}
UnlockServerList();
dwByteCount += 2; // for ending null
// Allocate memory.
pBuffer = NULL;
if( ( pBuffer = ( LPWSTR )LocalAlloc( LPTR, dwByteCount ) ) != NULL )
{
// Traverse list again and copy servers to buffer.
LPWSTR pTemp = pBuffer;
LockServerList();
pos = m_ServerList.GetHeadPosition();
while(pos)
{
// Go to the next server in the list
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if( pServer->IsState(SS_GOOD) )
{
wcscpy(pTemp, pServer->GetName());
pTemp += (wcslen(pServer->GetName()) + 1);
}
}
UnlockServerList();
*pTemp = L'\0'; // ending null
// write the registry entry
RegSetValueEx(hKeyWinAdmin, szConnections, 0, REG_MULTI_SZ, (PBYTE)pBuffer, dwByteCount);
LocalFree(pBuffer);
}
}
else
{
RegDeleteValue(hKeyWinAdmin, szConnections);
}
// persist treeview state
// send message to treeview to retreive tv state bits
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
DWORD dwTVStates = 0;
if( p != NULL )
{
dwTVStates = ( DWORD )p->SendMessage( WM_ADMIN_GET_TV_STATES , 0 , 0 );
}
RegSetValueEx( hKeyWinAdmin , szTVStates , 0 , REG_DWORD , ( PBYTE )&dwTVStates , sizeof( DWORD ) );
RegCloseKey(hKeyWinAdmin);
} // end CWinAdminDoc::WritePreferences
/*
static TCHAR DOMAIN_KEY[] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon");
static TCHAR PRIMARY_VAL[] = TEXT("CachePrimaryDomain");
static TCHAR CACHE_VAL[] = TEXT("DomainCache");
*/
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::BuildDomainList
//
// Read the list of trusted domains from the registry
// and build a linked list of CDomains
//
void CWinAdminDoc::BuildDomainList()
{
/*
HKEY hKey,hSubKey;
DWORD size = 128;
DWORD dwIndex = 0;
*/
PDOMAIN_CONTROLLER_INFO pDCI;
if( DsGetDcName( NULL ,
NULL ,
NULL ,
NULL ,
DS_RETURN_FLAT_NAME,
&pDCI ) == NO_ERROR )
{
CDomain *pDomain = new CDomain( pDCI->DomainName );
if(pDomain != NULL )
{
pDomain->SetCurrentDomain();
m_pCurrentDomain = pDomain;
AddDomain( pDomain );
}
NetApiBufferFree( pDCI );
// query for the other domains
LPWSTR szDomainNames = NULL;
if( NetEnumerateTrustedDomains( NULL ,
&szDomainNames ) == ERROR_SUCCESS )
{
LPWSTR pszDN = szDomainNames;
while( *pszDN )
{
CDomain *pNewDomain = new CDomain( pszDN );
if( pNewDomain != NULL )
{
AddDomain( pNewDomain );
}
pszDN += ( wcslen( pszDN ) + 1 );
}
NetApiBufferFree( szDomainNames );
}
}
} // end CWinAdminDoc::BuildDomainList
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::AddDomain
//
// Add a Domain to DomainList in sorted order
//
void CWinAdminDoc::AddDomain(CDomain *pNewDomain)
{
ASSERT(pNewDomain);
BOOLEAN bAdded = FALSE;
POSITION pos, oldpos;
int Index;
// Traverse the DomainList and insert this new Domain,
// keeping the list sorted by Name.
for(Index = 0, pos = m_DomainList.GetHeadPosition(); pos != NULL; Index++) {
oldpos = pos;
CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
if(wcscmp(pDomain->GetName(), pNewDomain->GetName()) > 0) {
// The new object belongs before the current list object.
m_DomainList.InsertBefore(oldpos, pNewDomain);
bAdded = TRUE;
// NOTE: If you add a critical section to protect the domain list,
// you should change this to a break; and unlock the list
// just before exiting this function
return;
}
}
// If we haven't yet added the Domain, add it now to the tail
// of the list.
if(!bAdded) {
m_DomainList.AddTail(pNewDomain);
}
} // end CWinAdminDoc::AddDomain
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::BuildWdList
//
// Read the list of Wds from the registry
// and build a linked list of CWds
//
void CWinAdminDoc::BuildWdList()
{
LONG Status;
ULONG Index, ByteCount, Entries;
WDNAME WdKey;
LONG QStatus;
WDCONFIG2 WdConfig;
TCHAR WdDll[MAX_PATH];
CWd *pWd;
// Initialize the Wd list.
for ( Index = 0, Entries = 1, ByteCount = sizeof(WDNAME);
(Status =
RegWdEnumerate( SERVERNAME_CURRENT,
&Index,
&Entries,
WdKey,
&ByteCount )) == ERROR_SUCCESS;
ByteCount = sizeof(WDNAME) ) {
if ( ( QStatus = RegWdQuery( SERVERNAME_CURRENT, WdKey, &WdConfig,
sizeof(WdConfig),
&ByteCount ) ) != ERROR_SUCCESS ) {
//If this is added back in, the signature of StandardErrorMessage has changed!!!!
#if 0
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, QStatus,
IDP_ERROR_REGWDQUERY, WdKey ))
return(FALSE);
#endif
}
/*
* Only place this Wd in the WdList if it's DLL is present
* on the system.
*/
GetSystemDirectory( WdDll, MAX_PATH );
lstrcat( WdDll, TEXT("\\Drivers\\") );
lstrcat( WdDll, WdConfig.Wd.WdDLL );
lstrcat( WdDll, TEXT(".sys" ) );
if ( _waccess( WdDll, 0 ) != 0 )
continue;
pWd = new CWd(&WdConfig, (PWDNAME)&WdKey);
m_WdList.AddTail(pWd);
}
} // end CWinAdminDoc::BuildWdList
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::Refresh
//
// Perform a Refresh
//
void CWinAdminDoc::Refresh()
{
// We don't want to refresh if we are currently doing one
if(m_InRefresh) return;
CWaitCursor Nikki;
m_InRefresh = TRUE;
// Wake up our background tasks that enumerates servers
POSITION pos = m_DomainList.GetHeadPosition();
while(pos) {
CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
pDomain->SetEnumEvent();
}
// Make each of the Server's background tasks enumerate WinStations
LockServerList();
pos = m_ServerList.GetHeadPosition();
while(pos) {
ULONG WSEventFlags;
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if(pServer->IsHandleGood() && pServer->IsState(SS_GOOD)) {
WinStationWaitSystemEvent(pServer->GetHandle(), WEVENT_FLUSH, &WSEventFlags);
}
}
UnlockServerList();
// If the current page is a processes page, tell appropriate process enumeration
// background thread to do their thing
if(m_CurrentView == VIEW_ALL_SERVERS && m_CurrentPage == PAGE_AS_PROCESSES) {
UpdateAllProcesses();
}
if(m_CurrentView == VIEW_DOMAIN && m_CurrentPage == PAGE_DOMAIN_PROCESSES) {
UpdateAllProcesses();
}
if((m_CurrentView == VIEW_SERVER && m_CurrentPage == PAGE_PROCESSES)
|| (m_CurrentView == VIEW_WINSTATION && m_CurrentPage == PAGE_WS_PROCESSES)) {
m_ProcessWakeUpEvent.SetEvent();
}
m_InRefresh = FALSE;
} // end CWinAdminDoc::Refresh
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::AddServer
//
// Add a Server to ServerList in sorted order
//
void CWinAdminDoc::AddServer(CServer *pNewServer)
{
ASSERT(pNewServer);
LockServerList();
BOOLEAN bAdded = FALSE;
POSITION pos, oldpos;
int Index;
// Traverse the ServerList and insert this new Server,
// keeping the list sorted by Name.
for(Index = 0, pos = m_ServerList.GetHeadPosition(); pos != NULL; Index++)
{
oldpos = pos;
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if( lstrcmpi( pServer->GetName() , pNewServer->GetName() ) > 0 )
{
// The new object belongs before the current list object.
m_ServerList.InsertBefore(oldpos, pNewServer);
bAdded = TRUE;
break;
}
}
// If we haven't yet added the Server, add it now to the tail
// of the list.
if(!bAdded)
{
m_ServerList.AddTail(pNewServer);
}
UnlockServerList();
} // end CWinAdminDoc::AddServer
//=----------------------------------------------------------------------------------
//= AddToFavoritesNow will add all persisted servers to the fav node and
//= connect to them as appropriate.
void CWinAdminDoc::AddToFavoritesNow( )
{
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
LPTSTR pszDomain = NULL;
LPTSTR pszServer = NULL;
LPTSTR pszDomServer = NULL;
int nJump = 0;
POSITION pos;
if( m_pszFavList != NULL )
{
pszDomServer = m_pszFavList;
while( *pszDomServer )
{
pos = m_DomainList.GetHeadPosition();
nJump = wcslen( pszDomServer );
pszDomain = pszDomServer;
TCHAR *pTemp = pszDomServer;
while( *pTemp )
{
if( *pTemp == L'/' )
{
break;
}
pTemp++;
}
if(*pTemp == L'/')
{
*pTemp = 0;
pTemp++;
pszServer = pTemp;
}
else
{
//there is no domain for this server
pszServer = pszDomServer;
pszDomain = NULL;
}
// let's check to see if server already exist primarily "this computer"
if( m_pCurrentServer != NULL && lstrcmpi( pszServer , m_pCurrentServer->GetName( ) ) == 0 )
{
p->SendMessage(WM_ADMIN_ADDSERVERTOFAV , 0 , (LPARAM)m_pCurrentServer );
}
else
{
CDomain *pDomain = NULL;
CServer *pServer = NULL;
if( pszDomain )
{
BOOL bFound = FALSE;
while( pos )
{
pDomain = (CDomain*)m_DomainList.GetNext(pos);
if( _wcsicmp( pDomain->GetName() , pszDomain ) == 0 )
{
bFound = TRUE;
break;
}
}
if(!bFound)
{
pDomain = new CDomain( pszDomain );
if( pDomain != NULL )
{
AddDomain( pDomain );
p->SendMessage( WM_ADMIN_ADD_DOMAIN , (WPARAM)NULL , ( LPARAM )pDomain );
}
}
}
pServer = new CServer( pDomain , pszServer , FALSE , FALSE );
if( pServer != NULL )
{
pServer->SetManualFind( );
AddServer(pServer);
p->SendMessage(WM_ADMIN_ADDSERVERTOFAV , 0 , (LPARAM)pServer);
}
}
pszDomServer += nJump + 1;
}
}
// check to see if we need to connect these servers.
LockServerList();
pos = m_ServerList.GetHeadPosition();
while( pos )
{
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if( ShouldConnect( pServer->GetName( ) ) )
{
if( pServer->GetTreeItemFromFav( ) != NULL )
{
pServer->Connect( );
}
}
}
UnlockServerList();
}
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::FindServerByName
//
// returns a pointer to a given CServer object if it is in our list
//
CServer* CWinAdminDoc::FindServerByName(TCHAR *pServerName)
{
ASSERT(pServerName);
LockServerList();
POSITION pos = m_ServerList.GetHeadPosition();
while(pos) {
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if( lstrcmpi( pServer->GetName() , pServerName ) == 0)
{
UnlockServerList();
return pServer;
}
}
UnlockServerList();
return NULL;
} // end CWinAdminDoc::FindServerByName
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::FindWdByName
//
// returns a pointer to a given CWd object if it is in our list
//
CWd* CWinAdminDoc::FindWdByName(TCHAR *pWdName)
{
ASSERT(pWdName);
LockWdList();
POSITION pos = m_WdList.GetHeadPosition();
while(pos) {
CWd *pWd = (CWd*)m_WdList.GetNext(pos);
if(wcscmp(pWd->GetName(), pWdName) == 0) {
UnlockWdList();
return pWd;
}
}
UnlockWdList();
return NULL;
} // end CWinAdminDoc::FindWdByName
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::SetTreeCurrent
//
void CWinAdminDoc::SetTreeCurrent(CObject* selected, NODETYPE type)
{
m_CurrentSelectedNode = selected;
m_CurrentSelectedType = type;
// We need to be able to check the current selected type from other
// threads, in particular when resetting, disconnecting and sending
// a message, to check that we still have a valid winstation
CWinAdminDoc::gm_CurrentSelType = type;
CString TitleString;
// Set the window title
switch(m_CurrentSelectedType) {
case NODE_ALL_SERVERS:
TitleString.LoadString(IDS_TREEROOT);
SetTitle(TitleString);
break;
case NODE_DOMAIN:
TitleString.Format(TEXT("\\\\%s"), ((CDomain*)selected)->GetName());
SetTitle(TitleString);
break;
case NODE_SERVER:
SetTitle(((CServer*)selected)->GetName());
break;
case NODE_WINSTATION:
SetTitle(((CWinStation*)selected)->GetServer()->GetName());
break;
case NODE_THIS_COMP:
TitleString.LoadString( IDS_THISCOMPUTER );
SetTitle( TitleString );
break;
case NODE_FAV_LIST:
TitleString.LoadString( IDS_FAVSERVERS );
SetTitle( TitleString );
break;
}
} // end CWinAdminDoc::SetTreeCurrent
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::SendWinStationMessage
//
// bTemp is TRUE if message is to be sent to the temporarily selected
// tree item.
//
void CWinAdminDoc::SendWinStationMessage(BOOL bTemp, MessageParms *pParms)
{
ASSERT(pParms);
// Are we sending a message to temporarily selected tree item?
if(bTemp)
{
// Is the temporarily selected item in the tree a WinStation?
if(m_TempSelectedType == NODE_WINSTATION)
{
// If the winstation we're working on disappears before we get here
// then just return
if (m_CurrentSelectedType != NODE_WINSTATION)
{
return;
}
pParms->pWinStation = (CWinStation*)m_pTempSelectedNode;
pParms->bActionOnCurrentSelection = TRUE;
AfxBeginThread((AFX_THREADPROC)CWinStation::SendMessage, pParms);
}
return;
}
// Is the WinStation selected in the tree?
if(m_CurrentSelectedType == NODE_WINSTATION)
{
pParms->pWinStation = (CWinStation*)m_CurrentSelectedNode;
pParms->bActionOnCurrentSelection = TRUE;
AfxBeginThread((AFX_THREADPROC)CWinStation::SendMessage, pParms);
}
// Go through the list of WinStations on the currently selected server
// and send messages to those that are selected
else if(m_CurrentView == VIEW_SERVER)
{
// Get a pointer to the selected server
CServer *pServer = (CServer*)m_CurrentSelectedNode;
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos)
{
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected())
{
// Make a copy of the MessageParms
MessageParms *pParmsCopy = new MessageParms;
if(pParmsCopy)
{
memcpy(pParmsCopy, pParms, sizeof(MessageParms));
// Start a thread to send the message
pParmsCopy->pWinStation = pWinStation;
pParmsCopy->bActionOnCurrentSelection = FALSE;
AfxBeginThread((AFX_THREADPROC)CWinStation::SendMessage, pParmsCopy);
}
}
}
// Unlock the list of WinStations
pServer->UnlockWinStationList();
// Delete MessageParms - we sent copies to the WinStation objects
// They will delete their copies
delete pParms;
}
else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN)
{
LockServerList();
POSITION pos2 = m_ServerList.GetHeadPosition();
while(pos2)
{
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos)
{
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected())
{
// Make a copy of the MessageParms
MessageParms *pParmsCopy = new MessageParms;
if(pParmsCopy)
{
memcpy(pParmsCopy, pParms, sizeof(MessageParms));
// Start a thread to send the message
pParmsCopy->pWinStation = pWinStation;
pParmsCopy->bActionOnCurrentSelection = FALSE;
AfxBeginThread((AFX_THREADPROC)CWinStation::SendMessage, pParmsCopy);
}
}
}
// Unlock the list of WinStations
pServer->UnlockWinStationList();
}
UnlockServerList();
// Delete MessageParms - we sent copies to the WinStation objects
// They will delete their copies
delete pParms;
}
} // end CWinAdminDoc::SendWinStationMessage
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::ConnectWinStation
//
// bTemp is TRUE if we are to connect to the temporarily selected tree item.
//
void CWinAdminDoc::ConnectWinStation(BOOL bTemp, BOOL bUser)
{
// Are we connecting to temporarily selected tree item?
if(bTemp) {
// Is the temporarily selected item in the tree a WinStation?
if(m_TempSelectedType == NODE_WINSTATION) {
((CWinStation*)m_pTempSelectedNode)->Connect(NULL);
}
return;
}
if(m_CurrentSelectedType == NODE_WINSTATION) {
((CWinStation*)m_CurrentSelectedNode)->Connect(NULL);
}
// Go through the list of WinStations on the currently selected server
// and disconnect those that are selected
else if(m_CurrentView == VIEW_SERVER) {
// Get a pointer to the selected server
CServer *pServer = (CServer*)m_CurrentSelectedNode;
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos) {
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected()) {
// do the connect
pWinStation->Connect(bUser);
break; // we can only connect to one WinStation
}
}
// Unlock the list of WinStations
pServer->UnlockWinStationList();
}
else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
LockServerList();
POSITION pos2 = m_ServerList.GetHeadPosition();
while(pos2) {
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos) {
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected()) {
// do the connect
pWinStation->Connect(bUser);
break; // we can only connect to one WinStation
}
}
// Unlock the list of WinStations
pServer->UnlockWinStationList();
}
UnlockServerList();
}
} // end CWinAdminDoc::ConnectWinStation
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::StatusWinStation
//
// bTemp is TRUE if we are to show status for the temporarily selected tree item.
//
void CWinAdminDoc::StatusWinStation(BOOL bTemp)
{
// Are we showing status for the temporarily selected tree item?
if(bTemp) {
// Is the temporarily selected item in the tree a WinStation?
if(m_TempSelectedType == NODE_WINSTATION) {
((CWinStation*)m_pTempSelectedNode)->ShowStatus();
}
return;
}
if(m_CurrentSelectedType == NODE_WINSTATION) {
((CWinStation*)m_CurrentSelectedNode)->ShowStatus();
}
// Go through the list of WinStations on the currently selected server
// and show status for those that are selected
else if(m_CurrentView == VIEW_SERVER) {
// Get a pointer to the selected server
CServer *pServer = (CServer*)m_CurrentSelectedNode;
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos) {
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected()) {
pWinStation->ShowStatus();
}
}
// Unlock the list of WinStations
pServer->UnlockWinStationList();
}
else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
LockServerList();
POSITION pos2 = m_ServerList.GetHeadPosition();
while(pos2) {
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos) {
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected()) {
pWinStation->ShowStatus();
}
}
// Unlock the list of WinStations
pServer->UnlockWinStationList();
}
UnlockServerList();
}
} // end CWinAdminDoc::StatusWinStation
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::DisconnectWinStation
//
// bTemp is TRUE if we are disconnecting the temporarily selected tree item.
//
void CWinAdminDoc::DisconnectWinStation(BOOL bTemp)
{
CWinStation * pCurWinStation;
CServer * pCurServer;
// Are we disconnecting the temporarily selected tree item?
if(bTemp)
{
// Is the temporarily selected item in the tree a WinStation?
if(m_TempSelectedType == NODE_WINSTATION)
{
// If the winstation we're working on disappears before we get here
// then just return
if (m_CurrentSelectedType != NODE_WINSTATION)
{
return;
}
// create a disconnect parameters structure
DisconnectParms * pDisconParms = new DisconnectParms;
if(pDisconParms)
{
// get currecnt selected node winstation and server
pCurWinStation = (CWinStation*)m_pTempSelectedNode;
pCurServer = pCurWinStation->GetServer();
pDisconParms->hServer = pCurServer->GetHandle();
pDisconParms->ulLogonId = pCurWinStation->GetLogonId();
pDisconParms->bActionOnCurrentSelection = TRUE;
AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, pDisconParms);
// the thread will delete pDisconParms
}
}
return;
}
if(m_CurrentSelectedType == NODE_WINSTATION)
{
// create a disconnect parameters structure
DisconnectParms *pDisconParms = new DisconnectParms;
if(pDisconParms)
{
// get currecnt selected node winstation and server
pCurWinStation = (CWinStation*)m_CurrentSelectedNode;
pCurServer = pCurWinStation->GetServer();
pDisconParms->hServer = pCurServer->GetHandle();
pDisconParms->ulLogonId = pCurWinStation->GetLogonId();
pDisconParms->bActionOnCurrentSelection = TRUE;
AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, pDisconParms);
// the thread will delete pDisconParms
}
}
// Go through the list of WinStations on the currently selected server
// and disconnect those that are selected
else if(m_CurrentView == VIEW_SERVER)
{
// Get a pointer to the selected server
CServer *pServer = (CServer*)m_CurrentSelectedNode;
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos)
{
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected())
{
// create a disconnect parameters structure
DisconnectParms *pDisconParms = new DisconnectParms;
if(pDisconParms)
{
// get currecnt selected node winstation and server
//pCurWinStation = (CWinStation*)m_pTempSelectedNode;
pCurServer = pWinStation->GetServer();
pDisconParms->hServer = pCurServer->GetHandle();
pDisconParms->ulLogonId = pWinStation->GetLogonId();
pDisconParms->bActionOnCurrentSelection = FALSE;
// Start a thread to do the disconnect
AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, pDisconParms);
// the thread will delete pDisconParms
}
}
}
// Unlock the list of WinStations
pServer->UnlockWinStationList();
}
else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN)
{
LockServerList();
POSITION pos2 = m_ServerList.GetHeadPosition();
while(pos2)
{
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos)
{
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected())
{
// create a disconnect parameters structure
DisconnectParms *pDisconParms = new DisconnectParms;
if(pDisconParms)
{
// get currecnt selected node winstation and server
//pCurWinStation = (CWinStation*)m_pTempSelectedNode;
pCurServer = pWinStation->GetServer();
pDisconParms->hServer = pCurServer->GetHandle();
pDisconParms->ulLogonId = pWinStation->GetLogonId();
pDisconParms->bActionOnCurrentSelection = FALSE;
// Start a thread to do the disconnect
AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, pDisconParms);
// the thread will delete pDisconParms
}
}
}
// Unlock the list of WinStations
pServer->UnlockWinStationList();
}
UnlockServerList();
}
} // end CWinAdminDoc::DisconnectWinStation
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::ResetWinStation
//
// bTemp is TRUE if we are to reset the temporarily selected tree item.
// bReset is TRUE if reset, FALSE if logoff
//
void CWinAdminDoc::ResetWinStation(BOOL bTemp, BOOL bReset)
{
// Are we resetting the temporarily selected tree item?
if(bTemp)
{
// Is the temporarily selected item in the tree a WinStation?
if(m_TempSelectedType == NODE_WINSTATION)
{
// If the winstation we're working on disappears before we get here
// then just return
if (m_CurrentSelectedType != NODE_WINSTATION)
{
return;
}
// create a reset parameters structure
ResetParms *pResetParms = new ResetParms;
if(pResetParms)
{
pResetParms->pWinStation = (CWinStation*)m_pTempSelectedNode;
pResetParms->bReset = bReset;
pResetParms->bActionOnCurrentSelection = TRUE;
AfxBeginThread((AFX_THREADPROC)CWinStation::Reset, pResetParms);
// the thread will delete pResetParms
}
}
return;
}
if(m_CurrentSelectedType == NODE_WINSTATION)
{
// create a reset parameters structure
ResetParms *pResetParms = new ResetParms;
if(pResetParms)
{
pResetParms->pWinStation = (CWinStation*)m_CurrentSelectedNode;
pResetParms->bReset = bReset;
pResetParms->bActionOnCurrentSelection = TRUE;
AfxBeginThread((AFX_THREADPROC)CWinStation::Reset, pResetParms);
// the thread will delete pResetParms
}
}
// Go through the list of WinStations on the currently selected server
// and reset those that are selected
else if(m_CurrentView == VIEW_SERVER)
{
// Get a pointer to the selected server
CServer *pServer = (CServer*)m_CurrentSelectedNode;
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos)
{
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected())
{
// create a reset parameters structure
ResetParms *pResetParms = new ResetParms;
if(pResetParms)
{
pResetParms->pWinStation = pWinStation;
pResetParms->bReset = bReset;
pResetParms->bActionOnCurrentSelection = FALSE;
// Start a thread to do the reset
AfxBeginThread((AFX_THREADPROC)CWinStation::Reset, pResetParms);
// the thread will delete pResetParms
}
}
}
// Unlock the list of WinStations
pServer->UnlockWinStationList();
}
else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN)
{
LockServerList();
POSITION pos2 = m_ServerList.GetHeadPosition();
while(pos2)
{
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos)
{
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if( pWinStationList != NULL && pWinStation->IsSelected() )
{
if( GetCurrentPage( ) == PAGE_AS_USERS && pWinStation->GetState() == State_Listen )
{
// from a user experience if the listener winstation has been selected from a
// previous page that went out of focus - then not skipping this winstation
// would appear as if we disconnected from every connected winstation.
continue;
}
// create a reset parameters structure
ResetParms *pResetParms = new ResetParms;
if( pResetParms != NULL )
{
pResetParms->pWinStation = pWinStation;
pResetParms->bReset = bReset;
pResetParms->bActionOnCurrentSelection = FALSE;
// Start a thread to do the reset
DBGMSG( L"TSMAN!CWinAdminDoc_ResetWinStation %s\n", pWinStation->GetName() );
AfxBeginThread((AFX_THREADPROC)CWinStation::Reset, pResetParms);
}
}
}
// Unlock the list of WinStations
pServer->UnlockWinStationList();
}
UnlockServerList();
}
} // end CWinAdminDoc::ResetWinStation
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::ShadowWinStation
//
// bTemp is TRUE if we are to shadow the temporarily selected tree item.
//
void CWinAdminDoc::ShadowWinStation(BOOL bTemp)
{
// Are we resetting the temporarily selected tree item?
if(bTemp) {
// Is the temporarily selected item in the tree a WinStation?
if(m_TempSelectedType == NODE_WINSTATION) {
((CWinStation*)m_pTempSelectedNode)->Shadow();
}
return;
}
// Is the WinStation selected in the tree?
if(m_CurrentSelectedType == NODE_WINSTATION) {
((CWinStation*)m_CurrentSelectedNode)->Shadow();
}
// Go through the list of WinStations on the currently selected server
// and send messages to those that are selected
else if(m_CurrentView == VIEW_SERVER) {
// Get a pointer to the selected server
CServer *pServer = (CServer*)m_CurrentSelectedNode;
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
BOOL IsLockAlreadyReleased = FALSE;
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos) {
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected()) {
pServer->UnlockWinStationList();
IsLockAlreadyReleased = TRUE;
pWinStation->Shadow();
break; // we can only shadow one WinStation
}
}
// Unlock the list of WinStations
if (IsLockAlreadyReleased == FALSE) {
pServer->UnlockWinStationList();
}
}
else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
LockServerList();
POSITION pos2 = m_ServerList.GetHeadPosition();
while(pos2) {
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
// Lock the server's list of WinStations
pServer->LockWinStationList();
// Get a pointer to the server's list of WinStations
CObList *pWinStationList = pServer->GetWinStationList();
BOOL IsLockAlreadyReleased = FALSE;
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos) {
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected()) {
pServer->UnlockWinStationList();
IsLockAlreadyReleased = TRUE;
pWinStation->Shadow();
break; // we can only shadow one WinStation
}
}
// Unlock the list of WinStations
if (IsLockAlreadyReleased == FALSE) {
pServer->UnlockWinStationList();
}
else
{
break; // we can only shadow one WinStation
}
}
UnlockServerList();
}
} // end CWinAdminDoc::ShadowWinStation
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::ServerConnect
//
void CWinAdminDoc::ServerConnect()
{
ODS( L"CWinAdminDoc::ServerConnect\n" );
// Is the Server selected in the tree?
if(m_TempSelectedType == NODE_SERVER)
{
CServer *pServer = (CServer*)m_pTempSelectedNode;
// Tell the server to connect
if ((pServer->GetState() == SS_BAD) && (pServer->HasLostConnection() || !(pServer->IsServerSane())))
{
ODS( L"\tDisconnecting from server\n" );
/* disconnect */
pServer->Disconnect( );
}
pServer->Connect();
}
else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN)
{
LockServerList();
POSITION pos = m_ServerList.GetHeadPosition();
ODS( L"\tenumerating from server list\n" );
while(pos) {
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
// If this Server is selected, connect to it
if( pServer->IsSelected() )
{
// Tell the server to connect
if ((pServer->GetState() == SS_BAD) && (pServer->HasLostConnection() || !(pServer->IsServerSane())))
{
ODS( L"\tDisconnecting from server\n" );
/* disconnect */
pServer->Disconnect( );
}
pServer->Connect();
}
}
UnlockServerList();
}
} // end CWinAdminDoc::ServerConnect
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::ServerDisconnect
//
void CWinAdminDoc::ServerDisconnect()
{
// Is the Server selected in the tree?
if(m_TempSelectedType == NODE_SERVER) {
CServer *pServer = (CServer*)m_pTempSelectedNode;
// Tell the server to disconnect
pServer->Disconnect();
}
else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
CString AString;
CDialog dlgWait;
dlgWait.Create(IDD_SHUTDOWN, NULL);
LockServerList();
// Do a first loop to signal the server background threads that they must stop
POSITION pos = m_ServerList.GetHeadPosition();
while(pos) {
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
// If this Server is selected, stop its background thread
if(pServer->IsSelected()) {
// thell the server background thread to stop
pServer->ClearBackgroundContinue();
}
}
// do a second loop to disconnect the servers
pos = m_ServerList.GetHeadPosition();
while(pos) {
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
// If this Server is selected, disconnect from it
if(pServer->IsSelected()) {
AString.Format(IDS_DISCONNECTING, pServer->GetName());
dlgWait.SetDlgItemText(IDC_SHUTDOWN_MSG, AString);
// Tell the server to disconnect
pServer->Disconnect();
}
}
UnlockServerList();
dlgWait.PostMessage(WM_CLOSE);
}
} // end CWinAdminDoc::ServerDisconnect
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::TempDomainConnectAllServers
//
// Connect to all the servers in temporarily selected Domain
//
void CWinAdminDoc::TempDomainConnectAllServers()
{
if(m_TempSelectedType == NODE_DOMAIN) {
((CDomain*)m_pTempSelectedNode)->ConnectAllServers();
}
} // end CWinAdminDoc::TempDomainConnectAllServers
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::TempDomainDisconnectAllServers
//
// Disconnect from all servers in temporarily selected Domain
//
void CWinAdminDoc::TempDomainDisconnectAllServers()
{
if(m_TempSelectedType == NODE_DOMAIN) {
((CDomain*)m_pTempSelectedNode)->DisconnectAllServers();
}
} // end CWinAdminDoc::TempDomainDisconnectAllServers
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CurrentDomainConnectAllServers
//
// Connect to all the servers in currently selected Domain
//
void CWinAdminDoc::CurrentDomainConnectAllServers()
{
if(m_CurrentSelectedType == NODE_DOMAIN) {
((CDomain*)m_CurrentSelectedNode)->ConnectAllServers();
}
} // end CWinAdminDoc::CurrentDomainConnectAllServers
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CurrentDomainDisconnectAllServers
//
// Disconnect from all servers in currently selected Domain
//
void CWinAdminDoc::CurrentDomainDisconnectAllServers()
{
if(m_CurrentSelectedType == NODE_DOMAIN) {
((CDomain*)m_CurrentSelectedNode)->DisconnectAllServers();
}
} // end CWinAdminDoc::CurrentDomainDisconnectAllServers
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::DomainFindServers
//
// Find all servers in a Domain
//
void CWinAdminDoc::DomainFindServers()
{
if(m_TempSelectedType == NODE_DOMAIN) {
CDomain *pDomain = (CDomain*)m_pTempSelectedNode;
if(!pDomain->GetThreadPointer()) pDomain->StartEnumerating();
}
} // end CWinAdminDoc::DomainFindServers
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::ConnectToAllServers
//
// Connect to all the servers
//
void CWinAdminDoc::ConnectToAllServers()
{
LockServerList();
POSITION pos = m_ServerList.GetHeadPosition();
while(pos) {
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
// If this server isn't currently connected, connect to it
if(pServer->IsState(SS_NOT_CONNECTED)) {
// Tell the server to connect
pServer->Connect();
}
}
UnlockServerList();
} // end CWinAdminDoc::ConnectToAllServers
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::DisconnectFromAllServers
//
// Disconnect from all the servers
//
void CWinAdminDoc::DisconnectFromAllServers()
{
CString AString;
CDialog dlgWait;
dlgWait.Create(IDD_SHUTDOWN, NULL);
// tell each domain thread to stop enumerating while we're shutting down all servers
#ifdef _STRESS_BUILD
g_fWaitForAllServersToDisconnect = 1;
#endif
POSITION pos;
LockServerList();
// Do a first loop to signal the server background threads that they must stop
pos = m_ServerList.GetHeadPosition();
while( pos )
{
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
// If this Server is currently connected, tell the server background thread to stop
if(pServer->GetState() != SS_NOT_CONNECTED)
{
pServer->ClearBackgroundContinue();
}
}
// do a second loop to disconnect the servers
pos = m_ServerList.GetHeadPosition();
while(pos)
{
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
// If this server is currently connected, disconnect from it
if(pServer->GetState() != SS_NOT_CONNECTED)
{
AString.Format(IDS_DISCONNECTING, pServer->GetName());
dlgWait.SetDlgItemText(IDC_SHUTDOWN_MSG, AString);
// Tell the server to disconnect
pServer->Disconnect();
}
}
UnlockServerList();
dlgWait.PostMessage(WM_CLOSE);
#ifdef _STRESS_BUILD
g_fWaitForAllServersToDisconnect = 0;
#endif
} // end CWinAdminDoc::DisconnectFromAllServers
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::FindAllServers
//
// find all Servers in all Domains
//
void CWinAdminDoc::FindAllServers()
{
if(m_bInShutdown) return;
POSITION pos = m_DomainList.GetHeadPosition();
while(pos) {
// Get a pointer to the domain
CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
// If this domain isn't currently enumerating servers, tell it to
if(!pDomain->GetThreadPointer()) pDomain->StartEnumerating();
}
} // end CWinAdminDoc::FindAllServers
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::TerminateProcess
//
void CWinAdminDoc::TerminateProcess()
{
if(m_CurrentView == VIEW_SERVER) {
// Get a pointer to the selected server
CServer *pServer = (CServer*)m_CurrentSelectedNode;
// Lock the server's list of Processes
pServer->LockProcessList();
// Get a pointer to the server's list of Processes
CObList *pProcessList = pServer->GetProcessList();
// Iterate through the Process list
POSITION pos = pProcessList->GetHeadPosition();
while(pos) {
CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
if(pProcess->IsSelected() && !pProcess->IsTerminating()) {
// Start a thread to do the terminate
AfxBeginThread((AFX_THREADPROC)CWinAdminDoc::TerminateProc, pProcess);
}
}
// Unlock the list of Processes
pServer->UnlockProcessList();
}
else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
POSITION pos2 = m_ServerList.GetHeadPosition();
while(pos2) {
// Get a pointer to the server
CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
// Lock the server's list of Processes
pServer->LockProcessList();
// Get a pointer to the server's list of Processes
CObList *pProcessList = pServer->GetProcessList();
// Iterate through the Process list
POSITION pos = pProcessList->GetHeadPosition();
while(pos) {
CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
if(pProcess->IsSelected() && !pProcess->IsTerminating()) {
// Start a thread to do the terminate
AfxBeginThread((AFX_THREADPROC)CWinAdminDoc::TerminateProc, pProcess);
}
}
// Unlock the list of Processes
pServer->UnlockProcessList();
}
}
else if(m_CurrentView == VIEW_WINSTATION) {
// Get the Server for the currently viewed WinStation
CServer *pServer = (CServer*)((CWinStation*)m_CurrentSelectedNode)->GetServer();
// Lock the server's list of Processes
pServer->LockProcessList();
// Get a pointer to the server's list of Processes
CObList *pProcessList = pServer->GetProcessList();
// Iterate through the Process list
POSITION pos = pProcessList->GetHeadPosition();
while(pos) {
CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
if(pProcess->IsSelected() && !pProcess->IsTerminating()
&& (pProcess->GetWinStation() == (CWinStation*)m_CurrentSelectedNode)) {
// Start a thread to do the terminate
AfxBeginThread((AFX_THREADPROC)CWinAdminDoc::TerminateProc, pProcess);
}
}
// Unlock the list of Processes
pServer->UnlockProcessList();
}
} // end CWinAdminDoc::TerminateProcess
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::TerminateProc
//
UINT CWinAdminDoc::TerminateProc(LPVOID parms)
{
ASSERT(parms);
CProcess *pProcess = (CProcess*)parms;
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
// Set the flag to say that we are trying to terminate this process
pProcess->SetTerminating();
CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
if(WinStationTerminateProcess(pProcess->GetServer()->GetHandle(),pProcess->GetPID(), 0))
{
// Send a message to remove the process from the view
if(p && ::IsWindow(p->GetSafeHwnd()))
{
p->SendMessage(WM_ADMIN_REMOVE_PROCESS, 0, (LPARAM)pProcess);
}
}
else
{
pProcess->ClearTerminating();
//Display Error Message
if(p && ::IsWindow(p->GetSafeHwnd()))
{
DWORD Error = GetLastError();
//We need this to know the length of the error message
//now that StandardErrorMessage requires that
CString tempErrorMessage;
tempErrorMessage.LoadString(IDS_CANNOT_TERMINATE);
StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
LOGONID_NONE,Error,tempErrorMessage.GetLength(),wcslen(pProcess->GetImageName()),
IDS_CANNOT_TERMINATE,pProcess->GetImageName());
}
}
return 0;
} // end CWinAdminDoc::TerminateProc
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CheckConnectAllowed
//
BOOL CWinAdminDoc::CheckConnectAllowed(CWinStation *pWinStation)
{
ASSERT(pWinStation);
// If they are the same WinStation, don't let them connect
if(pWinStation->GetServer()->IsCurrentServer()
&& ((CWinAdminApp*)AfxGetApp())->GetCurrentLogonId() == pWinStation->GetLogonId())
return FALSE;
if((((CWinAdminApp*)AfxGetApp())->GetCurrentWSFlags() & WDF_SHADOW_SOURCE)
&& !pWinStation->HasOutstandingThreads()
&& !pWinStation->IsDown()
&& !pWinStation->IsListener()
&& !pWinStation->IsSystemConsole()
&& (pWinStation->IsDisconnected() || pWinStation->IsActive())
&& pWinStation->IsOnCurrentServer())
return TRUE;
return FALSE;
} // end CWinAdminDoc::CheckConnectAllowed
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CheckDisconnectAllowed
//
BOOL CWinAdminDoc::CheckDisconnectAllowed(CWinStation *pWinStation)
{
ASSERT(pWinStation);
if(!pWinStation->HasOutstandingThreads()
&& !pWinStation->IsDown()
&& !pWinStation->IsListener()
&& !pWinStation->IsSystemConsole()
&& pWinStation->IsConnected())
return TRUE;
return FALSE;
} // end CWinAdminDoc::CheckDisconnectAllowed
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CheckResetAllowed
//
BOOL CWinAdminDoc::CheckResetAllowed(CWinStation *pWinStation)
{
ASSERT(pWinStation);
if(!pWinStation->HasOutstandingThreads()
&& !pWinStation->IsSystemConsole())
return TRUE;
return FALSE;
} // end CWinAdminDoc::CheckResetAllowed
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CheckShadowAllowed
//
BOOL CWinAdminDoc::CheckShadowAllowed(CWinStation *pWinStation)
{
ASSERT(pWinStation);
// If they are the same WinStation, don't let them shadow
if( pWinStation->GetServer()->IsCurrentServer() &&
((CWinAdminApp*)AfxGetApp())->GetCurrentLogonId() == pWinStation->GetLogonId() )
{
return FALSE;
}
if(!pWinStation->HasOutstandingThreads() &&
!pWinStation->IsDown() && // winstation is not down
!pWinStation->IsListener() && // not a listening winstation
!pWinStation->IsDisconnected() && //not disconnected
(((CWinAdminApp*)AfxGetApp())->GetCurrentWSFlags() & WDF_SHADOW_SOURCE) && // We are valid shadow source, query winstation's wdflag in registry
(pWinStation->CanBeShadowed()) && // target can be shadow.
(pWinStation->GetState() != State_Shadow)) // target is not already in shadow
{
return TRUE;
}
return FALSE;
} // end CWinAdminDoc::CheckShadowAllowed
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CheckSendMessageAllowed
//
BOOL CWinAdminDoc::CheckSendMessageAllowed(CWinStation *pWinStation)
{
ASSERT(pWinStation);
if(!pWinStation->HasOutstandingThreads()
&& !pWinStation->IsDown()
&& !pWinStation->IsListener()
&& pWinStation->IsConnected())
return TRUE;
return FALSE;
} // end CWinAdminDoc::CheckSendMessageAllowed
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CheckStatusAllowed
//
BOOL CWinAdminDoc::CheckStatusAllowed(CWinStation *pWinStation)
{
ASSERT(pWinStation);
if(!pWinStation->HasOutstandingThreads()
&& !pWinStation->IsDown()
&& !pWinStation->IsDisconnected()
&& !pWinStation->IsIdle()
&& !pWinStation->IsListener()
&& !pWinStation->IsSystemConsole())
return TRUE;
return FALSE;
} // end CWinAdminDoc::CheckStatusAllowed
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CheckActionAllowed
//
BOOL CWinAdminDoc::CheckActionAllowed(BOOL (*CheckFunction)(CWinStation *pWinStation), BOOL AllowMultipleSelected)
{
ASSERT(CheckFunction);
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a WinStation selected in the tree?
if(m_CurrentSelectedType == NODE_WINSTATION)
{
CWinStation *pWinStation = (CWinStation*)m_CurrentSelectedNode;
return CheckFunction(pWinStation);
}
// We only care if the current view is Server or All Listed Servers
if(m_CurrentView == VIEW_SERVER)
{
// We need to make sure we are on the WinStation or Users page
if(m_CurrentPage != PAGE_WINSTATIONS && m_CurrentPage != PAGE_USERS)
{
return FALSE;
}
int NumSelected = 0;
CServer *pServer = (CServer*)m_CurrentSelectedNode;
// If there aren't any WinStations selected on this server, return
if(!pServer->GetNumWinStationsSelected())
{
return FALSE;
}
pServer->LockWinStationList();
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos)
{
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected())
{
if(!CheckFunction(pWinStation))
{
pServer->UnlockWinStationList();
return FALSE;
}
NumSelected++;
if(!AllowMultipleSelected && NumSelected > 1)
{
pServer->UnlockWinStationList();
return FALSE;
}
}
}
pServer->UnlockWinStationList();
// If we got here, all the selected WinStations passed our criteria
if(NumSelected) return TRUE;
}
else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN)
{
// If we are doing a refresh, we can't do anything else
if(m_InRefresh) return FALSE;
// We need to make sure we are on the WinStation or Users page
if(m_CurrentPage != PAGE_AS_WINSTATIONS && m_CurrentPage != PAGE_AS_USERS
&& m_CurrentPage != PAGE_DOMAIN_WINSTATIONS && m_CurrentPage != PAGE_DOMAIN_USERS)
return FALSE;
int NumSelected = 0;
LockServerList();
POSITION pos1 = m_ServerList.GetHeadPosition();
while(pos1) {
CServer *pServer = (CServer*)m_ServerList.GetNext(pos1);
// Are there any WinStations selected on this server?
if(pServer->GetNumWinStationsSelected()) {
pServer->LockWinStationList();
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos) {
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected()) {
if(!CheckFunction(pWinStation)) {
pServer->UnlockWinStationList();
UnlockServerList();
return FALSE;
}
NumSelected++;
if(!AllowMultipleSelected && NumSelected > 1) {
pServer->UnlockWinStationList();
UnlockServerList();
return FALSE;
}
}
}
pServer->UnlockWinStationList();
} // end if(pServer->GetNumWinStationsSelected())
}
UnlockServerList();
// If we got this far, all the selected WinStations passed the criteria
if(NumSelected) return TRUE;
}
return FALSE;
} // end CWinAdminDoc::CheckActionAllowed
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanConnect
//
// Returns TRUE if the currently selected item in views can be Connected to
//
BOOL CWinAdminDoc::CanConnect()
{
return CheckActionAllowed(CheckConnectAllowed, FALSE);
} // end CWinAdminDoc::CanConnect
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanDisconnect
//
// Returns TRUE if the currently selected item in views can be Disconnected
//
BOOL CWinAdminDoc::CanDisconnect()
{
return CheckActionAllowed(CheckDisconnectAllowed, TRUE);
} // end CWinAdminDoc::CanDisconnect
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanReset
//
// Returns TRUE if the currently selected item in views can be Reset
//
BOOL CWinAdminDoc::CanReset()
{
return CheckActionAllowed(CheckResetAllowed, TRUE);
} // end CWinAdminDoc::CanReset
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanShadow
//
// Returns TRUE if the currently selected item in views can be Shadowed
//
BOOL CWinAdminDoc::CanShadow()
{
return CheckActionAllowed(CheckShadowAllowed, FALSE);
} // end CWinAdminDoc::CanShadow
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanSendMessage
//
// Returns TRUE if the currently selected item in views can be sent a message
//
BOOL CWinAdminDoc::CanSendMessage()
{
return CheckActionAllowed(CheckSendMessageAllowed, TRUE);
} // end CWinAdminDoc::CanSendMessage
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanStatus
//
// Returns TRUE if the currently selected item in views can show Status
//
BOOL CWinAdminDoc::CanStatus()
{
return CheckActionAllowed(CheckStatusAllowed, TRUE);
} // end CWinAdminDoc::CanStatus
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanLogoff
//
// Returns TRUE if the currently selected item in views can be Logged Off
//
BOOL CWinAdminDoc::CanLogoff()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a WinStation selected in the tree?
if(m_CurrentSelectedType == NODE_WINSTATION) {
return FALSE;
}
// We only care if the current view is Server or All Listed Servers
if(m_CurrentView == VIEW_SERVER) {
// We need to make sure we are on the Users page
if(m_CurrentPage != PAGE_USERS) return FALSE;
BOOL Answer = FALSE;
CServer *pServer = (CServer*)m_CurrentSelectedNode;
// If there aren't any WinStations selected on this server, return
if(!pServer->GetNumWinStationsSelected()) return FALSE;
pServer->LockWinStationList();
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos) {
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected()) {
if(!pWinStation->HasOutstandingThreads())
Answer = TRUE;
}
}
pServer->UnlockWinStationList();
return Answer;
} else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
// If we are doing a refesh, we can't do anything else
if(m_InRefresh) return FALSE;
// We need to make sure we are on the Users page
if(m_CurrentPage != PAGE_AS_USERS && m_CurrentPage != PAGE_DOMAIN_USERS) return FALSE;
BOOL Answer = FALSE;
LockServerList();
POSITION pos1 = m_ServerList.GetHeadPosition();
while(pos1) {
CServer *pServer = (CServer*)m_ServerList.GetNext(pos1);
// Are there any WinStations selected on this server?
if(pServer->GetNumWinStationsSelected()) {
pServer->LockWinStationList();
CObList *pWinStationList = pServer->GetWinStationList();
// Iterate through the WinStation list
POSITION pos = pWinStationList->GetHeadPosition();
while(pos) {
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
if(pWinStation->IsSelected()) {
if(!pWinStation->HasOutstandingThreads())
Answer = TRUE;
}
}
pServer->UnlockWinStationList();
} // end if(pServer->GetNumWinStationsSelected())
}
UnlockServerList();
return Answer;
}
return FALSE;
} // end CWinAdminDoc::CanLogoff
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanTerminate
//
// Returns TRUE if the currently selected item in views can be Terminated
//
BOOL CWinAdminDoc::CanTerminate()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// We have to be in All Selected Servers, Server, or WinStation view
if((m_CurrentView == VIEW_ALL_SERVERS && m_CurrentPage == PAGE_AS_PROCESSES)
|| (m_CurrentView == VIEW_DOMAIN && m_CurrentPage == PAGE_DOMAIN_PROCESSES)) {
// If we are doing a refresh, we can't do anything else
if(m_InRefresh) return FALSE;
// Loop through all the servers and see if any processes are selected
LockServerList();
POSITION pos2 = m_ServerList.GetHeadPosition();
while(pos2) {
CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
// Are there any processes selected on this server?
if(pServer->GetNumProcessesSelected()) {
pServer->LockProcessList();
CObList *pProcessList = pServer->GetProcessList();
POSITION pos = pProcessList->GetHeadPosition();
while(pos) {
CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
// We only need one process to be selected
if(pProcess->IsSelected() && !pProcess->IsTerminating()) {
pServer->UnlockProcessList();
UnlockServerList();
return TRUE;
}
}
pServer->UnlockProcessList();
} // end if(pServer->GetNumProcessesSelected())
}
UnlockServerList();
return FALSE;
}
if(m_CurrentView == VIEW_SERVER && m_CurrentPage == PAGE_PROCESSES) {
CServer *pServer = (CServer*)m_CurrentSelectedNode;
// If there aren't any processes selected on this server, return
if(!pServer->GetNumProcessesSelected()) return FALSE;
pServer->LockProcessList();
CObList *pProcessList = pServer->GetProcessList();
POSITION pos = pProcessList->GetHeadPosition();
while(pos) {
CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
// We only need one process to be selected
if(pProcess->IsSelected() && !pProcess->IsTerminating()) {
pServer->UnlockProcessList();
return TRUE;
}
}
pServer->UnlockProcessList();
return FALSE;
}
if(m_CurrentView == VIEW_WINSTATION && m_CurrentPage == PAGE_WS_PROCESSES) {
CServer *pServer = (CServer*)((CWinStation*)m_CurrentSelectedNode)->GetServer();
pServer->LockProcessList();
CObList *pProcessList = pServer->GetProcessList();
POSITION pos = pProcessList->GetHeadPosition();
while(pos) {
CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
// We only need one process to be selected
if(pProcess->IsSelected() && !pProcess->IsTerminating()) {
pServer->UnlockProcessList();
return TRUE;
}
}
pServer->UnlockProcessList();
return FALSE;
}
return FALSE;
} // end CWinAdminDoc::CanTerminate
//=--------------------------------------------------------
BOOL CWinAdminDoc::IsAlreadyFavorite( )
{
if(m_TempSelectedType == NODE_SERVER)
{
CServer *pServer = (CServer*)m_pTempSelectedNode;
if( pServer->GetTreeItemFromFav( ) != NULL )
{
return TRUE;
}
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanServerConnect
//
// Returns TRUE if the currently selected server in views can be connected to
//
BOOL CWinAdminDoc::CanServerConnect()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a Server selected in the tree?
if(m_TempSelectedType == NODE_SERVER) {
if(((CServer*)m_pTempSelectedNode)->GetState() == SS_NOT_CONNECTED ||
((CServer*)m_pTempSelectedNode)->GetState() == SS_BAD ) return TRUE;
}
// Is a Server selected in the tree?
else if(m_CurrentSelectedType == NODE_SERVER) {
if(((CServer*)m_CurrentSelectedNode)->GetState() == SS_NOT_CONNECTED ||
((CServer*)m_CurrentSelectedNode)->GetState() == SS_BAD ) return TRUE;
}
// We only care if the current view is Domain or All Listed Servers
else if(m_CurrentView == VIEW_DOMAIN) {
// We need to make sure we are on the Servers page
if(m_CurrentPage != PAGE_DOMAIN_SERVERS) return FALSE;
int NumSelected = 0;
CDomain *pDomain = (CDomain*)m_CurrentSelectedNode;
LockServerList();
// Iterate through the Server list
POSITION pos = m_ServerList.GetHeadPosition();
while(pos) {
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if(pServer->IsSelected() && pServer->GetDomain() == pDomain) {
if(!pServer->IsState(SS_NOT_CONNECTED)) {
UnlockServerList();
return FALSE;
}
NumSelected++;
}
}
UnlockServerList();
// If we got here, all the selected Servers passed our criteria
if(NumSelected) return TRUE;
}
else if(m_CurrentView == VIEW_ALL_SERVERS) {
// We need to make sure we are on the Servers page
if(m_CurrentPage != PAGE_AS_SERVERS) return FALSE;
int NumSelected = 0;
LockServerList();
// Iterate through the Server list
POSITION pos = m_ServerList.GetHeadPosition();
while(pos) {
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if(pServer->IsSelected()) {
if(!pServer->IsState(SS_NOT_CONNECTED)) {
UnlockServerList();
return FALSE;
}
NumSelected++;
}
}
UnlockServerList();
// If we got here, all the selected Servers passed our criteria
if(NumSelected) return TRUE;
}
return FALSE;
} // end CWinAdminDoc::CanServerConnect
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanServerDisconnect
//
// Returns TRUE if the currently selected server in views can be disconnected from
//
BOOL CWinAdminDoc::CanServerDisconnect()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a Server selected in the tree?
if(m_TempSelectedType == NODE_SERVER) {
if(((CServer*)m_pTempSelectedNode)->GetState() == SS_GOOD) return TRUE;
}
// Is a Server selected in the tree?
else if(m_CurrentSelectedType == NODE_SERVER) {
if(((CServer*)m_CurrentSelectedNode)->GetState() == SS_GOOD) return TRUE;
}
// We only care if the current view is Domain or All Listed Servers
else if(m_CurrentView == VIEW_DOMAIN) {
// We need to make sure we are on the Servers page
if(m_CurrentPage != PAGE_DOMAIN_SERVERS) return FALSE;
int NumSelected = 0;
CDomain *pDomain = (CDomain*)m_CurrentSelectedNode;
LockServerList();
// Iterate through the Server list
POSITION pos = m_ServerList.GetHeadPosition();
while(pos) {
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if(pServer->IsSelected() && pServer->GetDomain() == pDomain) {
if(!pServer->IsState(SS_GOOD)) {
UnlockServerList();
return FALSE;
}
NumSelected++;
}
}
UnlockServerList();
// If we got here, all the selected Servers passed our criteria
if(NumSelected) return TRUE;
}
else if(m_CurrentView == VIEW_ALL_SERVERS) {
// We need to make sure we are on the Servers page
if(m_CurrentPage != PAGE_AS_SERVERS) return FALSE;
int NumSelected = 0;
LockServerList();
// Iterate through the Server list
POSITION pos = m_ServerList.GetHeadPosition();
while(pos) {
CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
if(pServer->IsSelected()) {
if(!pServer->IsState(SS_GOOD)) {
UnlockServerList();
return FALSE;
}
NumSelected++;
}
}
UnlockServerList();
// If we got here, all the selected Servers passed our criteria
if(NumSelected) return TRUE;
}
return FALSE;
} // end CWinAdminDoc::CanServerDisconnect
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanTempConnect
//
// Returns TRUE if the temporarily selected item in views can be Connected to
//
BOOL CWinAdminDoc::CanTempConnect()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a WinStation selected in the tree?
if(m_TempSelectedType == NODE_WINSTATION) {
return CheckConnectAllowed((CWinStation*)m_pTempSelectedNode);
}
return FALSE;
} // end CWinAdminDoc::CanTempConnect
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanTempDisconnect
//
// Returns TRUE if the temporarily selected item in views can be Disconnected
//
BOOL CWinAdminDoc::CanTempDisconnect()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a WinStation selected in the tree?
if(m_TempSelectedType == NODE_WINSTATION) {
return CheckDisconnectAllowed((CWinStation*)m_pTempSelectedNode);
}
return FALSE;
} // end CWinAdminDoc::CanTempDisconnect
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanTempReset
//
// Returns TRUE if the temporarily selected item in views can be Reset
//
BOOL CWinAdminDoc::CanTempReset()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a WinStation selected in the tree?
if(m_TempSelectedType == NODE_WINSTATION)
{
// If the winstation we're working on disappears before we get here
// then just return
if (m_CurrentSelectedType == NODE_WINSTATION)
{
return CheckResetAllowed((CWinStation*)m_pTempSelectedNode);
}
}
return FALSE;
} // end CWinAdminDoc::CanTempReset
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanTempShadow
//
// Returns TRUE if the temporarily selected item in views can be Shadowed
//
BOOL CWinAdminDoc::CanTempShadow()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a WinStation selected in the tree?
if(m_TempSelectedType == NODE_WINSTATION) {
return CheckShadowAllowed((CWinStation*)m_pTempSelectedNode);
}
return FALSE;
} // end CWinAdminDoc::CanTempShadow
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanTempSendMessage
//
// Returns TRUE if the temporarily selected item in views can be sent a message
//
BOOL CWinAdminDoc::CanTempSendMessage()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a WinStation selected in the tree?
if(m_TempSelectedType == NODE_WINSTATION) {
return CheckSendMessageAllowed((CWinStation*)m_pTempSelectedNode);
}
return FALSE;
} // end CWinAdminDoc::CanTempSendMessage
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanTempStatus
//
// Returns TRUE if the temporarily selected item in views can show Status
//
BOOL CWinAdminDoc::CanTempStatus()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a WinStation selected in the tree?
if(m_TempSelectedType == NODE_WINSTATION) {
return CheckStatusAllowed((CWinStation*)m_pTempSelectedNode);
}
return FALSE;
} // end CWinAdminDoc::CanTempStatus
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanTempDomainConnect
//
// Returns TRUE if the temporarily selected Domain in tree can have all it's
// Servers connected/disconnected to/from.
//
BOOL CWinAdminDoc::CanTempDomainConnect()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a Domain selected in the tree?
if(m_TempSelectedType == NODE_DOMAIN) {
if(((CDomain*)m_pTempSelectedNode)->IsState(DS_ENUMERATING))
return TRUE;
}
return FALSE;
} // end CWinAdminDoc::CanTempDomainConnect
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanTempDomainFindServers
//
// Returns TRUE if the temporarily selected Domain in tree can go out
// and find Servers
//
BOOL CWinAdminDoc::CanTempDomainFindServers()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a Domain selected in the tree?
if(m_TempSelectedType == NODE_DOMAIN) {
if(!((CDomain*)m_pTempSelectedNode)->GetThreadPointer())
return TRUE;
}
return FALSE;
} // end CWinAdminDoc::CanTempDomainFindServers
/////////////////////////////////////////////////////////////////////////////
// CWinAdminDoc::CanDomainConnect
//
// Returns TRUE if the currently selected Domain in tree can have all it's
// Servers connected/disconnected to/from.
//
BOOL CWinAdminDoc::CanDomainConnect()
{
// If we are shutting down, we don't care anymore
if(m_bInShutdown) return FALSE;
// Is a Domain selected in the tree?
if(m_CurrentSelectedType == NODE_DOMAIN) {
if(((CDomain*)m_CurrentSelectedNode)->IsState(DS_ENUMERATING))
return TRUE;
}
return FALSE;
} // end CWinAdminDoc::CanDomainConnect
//------------------------------------------------------------------------------
void CWinAdminDoc::ServerAddToFavorites( BOOL bAdd )
{
ODS( L"CWinAdminDoc::ServerAddToFavorites\n");
// we got here from a context menu selection
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
if(m_TempSelectedType == NODE_SERVER && pDoc != NULL )
{
CServer* pServer = ( CServer* )m_pTempSelectedNode;
if( pServer != NULL )
{
// test to see if the server is being removed
if( pServer->IsState(SS_DISCONNECTING) )
{
ODS( L"=-sneaky popup menu was up when server went away\n=-not adding server to favs\n");
return;
}
CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
if( p !=NULL && ::IsWindow(p->GetSafeHwnd() ) )
{
// ok we're off to treeview ville
if( bAdd )
{
p->SendMessage(WM_ADMIN_ADDSERVERTOFAV , 0 , (LPARAM)pServer);
}
else
{
p->SendMessage( WM_ADMIN_REMOVESERVERFROMFAV, 0 , (LPARAM)pServer);
}
}
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// CWinStation Member Functions
//
//////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CWinStation::CWinStation
//
CWinStation::CWinStation(CServer *pServer, PLOGONID pLogonId)
{
ASSERT(pServer);
m_WinStationFlags = 0L;
m_OutstandingThreads = 0;
m_hTreeItem = NULL;
m_hFavTree = NULL;
m_hTreeThisComputer = NULL;
m_pWd = NULL;
m_UserName[0] = '\0';
m_WdName[0] = '\0';
m_ClientName[0] = '\0';
m_Comment[0] = '\0';
m_SdClass = SdNone;
m_LogonTime.HighPart = 0L;
m_LogonTime.LowPart = 0L;
m_LastInputTime.HighPart = 0L;
m_LastInputTime.LowPart = 0L;
m_CurrentTime.HighPart = 0L;
m_CurrentTime.LowPart = 0L;
m_IdleTime.days = 0;
m_IdleTime.hours = 0;
m_IdleTime.minutes = 0;
m_IdleTime.seconds = 0;
m_pExtensionInfo = NULL;
m_pExtWinStationInfo = NULL;
m_pExtModuleInfo = NULL;
m_NumModules = 0;
m_ProtocolType = 0;
m_clientDigProductId[0] = '\0';
SetCurrent();
m_pServer = pServer;
m_LogonId = pLogonId->LogonId;
wcscpy(m_Name, pLogonId->WinStationName);
m_State = pLogonId->State;
m_SortOrder = SortOrder[pLogonId->State];
HANDLE Handle = m_pServer->GetHandle();
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
ULONG Length;
PDCONFIG PdConfig;
if(WinStationQueryInformation(Handle, m_LogonId, WinStationPd, &PdConfig,
sizeof(PDCONFIG), &Length)) {
m_SdClass = PdConfig.Create.SdClass;
wcscpy(m_PdName, PdConfig.Create.PdName);
if(m_SdClass == SdAsync) {
CDCONFIG CdConfig;
if(WinStationQueryInformation(Handle, m_LogonId, WinStationCd, &CdConfig,
sizeof(CDCONFIG), &Length)) {
if(CdConfig.CdClass != CdModem) SetDirectAsync();
}
}
}
WDCONFIG WdConfig;
if(WinStationQueryInformation(Handle, m_LogonId, WinStationWd, &WdConfig,
sizeof(WDCONFIG), &Length)) {
wcscpy(m_WdName, WdConfig.WdName);
m_pWd = pDoc->FindWdByName(m_WdName);
// if(WdConfig.WdFlag & WDF_SHADOW_TARGET) SetCanBeShadowed();
WINSTATIONCLIENT WsClient;
if(WinStationQueryInformation(Handle, m_LogonId, WinStationClient, &WsClient,
sizeof(WINSTATIONCLIENT), &Length)) {
wcscpy(m_ClientName, WsClient.ClientName);
wcscpy(m_clientDigProductId, WsClient.clientDigProductId);
}
}
WINSTATIONCONFIG WsConfig;
if(WinStationQueryInformation(Handle, m_LogonId, WinStationConfiguration,
&WsConfig, sizeof(WINSTATIONCONFIG), &Length)) {
wcscpy(m_Comment, WsConfig.Comment);
if(WdConfig.WdFlag & WDF_SHADOW_TARGET)
{
//
// WHY we have IsDisconnected() then IsConnected() ?
// WHY we don't allow shadowing view only session
//
if( (!((IsDisconnected()) &&
((WsConfig.User.Shadow == Shadow_EnableInputNotify) ||
(WsConfig.User.Shadow == Shadow_EnableNoInputNotify))))
|| (IsConnected()) )
{
SetCanBeShadowed();
}
}
}
WINSTATIONINFORMATION WsInfo;
if(WinStationQueryInformation(Handle, m_LogonId, WinStationInformation, &WsInfo,
sizeof(WINSTATIONINFORMATION), &Length))
{
// the state may have already changed
m_State = WsInfo.ConnectState;
wcscpy(m_UserName, WsInfo.UserName);
m_LogonTime = WsInfo.LogonTime;
m_LastInputTime = IsActive() ? WsInfo.LastInputTime : WsInfo.DisconnectTime;
m_CurrentTime = WsInfo.CurrentTime;
// Calculate elapsed time
if((IsActive() || IsDisconnected()) && m_LastInputTime.QuadPart <= m_CurrentTime.QuadPart && m_LastInputTime.QuadPart)
{
LARGE_INTEGER DiffTime = CalculateDiffTime(m_LastInputTime, m_CurrentTime);
ULONG_PTR d_time = ( ULONG_PTR )DiffTime.QuadPart;
ELAPSEDTIME IdleTime;
// Calculate the days, hours, minutes, seconds since specified time.
IdleTime.days = (USHORT)(d_time / 86400L); // days since
d_time = d_time % 86400L; // seconds => partial day
IdleTime.hours = (USHORT)(d_time / 3600L); // hours since
d_time = d_time % 3600L; // seconds => partial hour
IdleTime.minutes = (USHORT)(d_time / 60L); // minutes since
IdleTime.seconds = (USHORT)(d_time % 60L);// seconds remaining
m_IdleTime = IdleTime;
TCHAR IdleTimeString[MAX_ELAPSED_TIME_LENGTH];
ElapsedTimeString( &IdleTime, FALSE, IdleTimeString);
}
}
WINSTATIONCLIENT ClientData;
// Get the protocol this WinStation is using
if(WinStationQueryInformation( Handle,
m_LogonId,
WinStationClient,
&ClientData,
sizeof(WINSTATIONCLIENT),
&Length ) ) {
m_ProtocolType = ClientData.ProtocolType;
m_EncryptionLevel = ClientData.EncryptionLevel;
}
// If there is a user, set a flag bit
if(wcslen(m_UserName)) SetHasUser();
else ClearHasUser();
// Remember when we got this information
SetLastUpdateClock();
SetQueriesSuccessful();
// If there is an extension DLL loaded, allow it to add it's own info for this WinStation
LPFNEXWINSTATIONINITPROC InitProc = ((CWinAdminApp*)AfxGetApp())->GetExtWinStationInitProc();
if(InitProc) {
m_pExtensionInfo = (*InitProc)(Handle, m_LogonId);
if(m_pExtensionInfo) {
LPFNEXGETWINSTATIONINFOPROC InfoProc = ((CWinAdminApp*)AfxGetApp())->GetExtGetWinStationInfoProc();
if(InfoProc) {
m_pExtWinStationInfo = (*InfoProc)(m_pExtensionInfo);
}
}
}
} // end CWinStation::CWinStation
/////////////////////////////////////////////////////////////////////////////
// CWinStation::~CWinStation
//
CWinStation::~CWinStation()
{
// Remove all of the processes attributed to this WinStation
// from the Server's list
m_pServer->RemoveWinStationProcesses(this);
// If there is an extension DLL, let it cleanup anything it added to this WinStation
LPFNEXWINSTATIONCLEANUPPROC CleanupProc = ((CWinAdminApp*)AfxGetApp())->GetExtWinStationCleanupProc();
if(CleanupProc) {
(*CleanupProc)(m_pExtensionInfo);
}
if(m_pExtModuleInfo) {
// Get the extension DLL's function to free the module info
LPFNEXFREEWINSTATIONMODULESPROC FreeModulesProc = ((CWinAdminApp*)AfxGetApp())->GetExtFreeWinStationModulesProc();
if(FreeModulesProc) {
(*FreeModulesProc)(m_pExtModuleInfo);
} else {
TRACE0("WAExGetWinStationModules exists without WAExFreeWinStationModules\n");
ASSERT(0);
}
}
} // end CWinStation::~CWinStation
/////////////////////////////////////////////////////////////////////////////
// CWinStation::Update
//
// Updates this WinStation with new data from another CWinStation
//
BOOL CWinStation::Update(CWinStation *pWinStation)
{
ASSERT(pWinStation);
// Check for any information that has changed
BOOL bInfoChanged = FALSE;
// Check the State
if(m_State != pWinStation->GetState()) {
// If the old state was disconnected, then we want to
// go out and get the module (client) information again
if(m_State == State_Disconnected)
ClearAdditionalDone();
m_State = pWinStation->GetState();
// Sort order only changes when state changes
m_SortOrder = pWinStation->GetSortOrder();
bInfoChanged = TRUE;
}
// Check the UserName
if(wcscmp(m_UserName, pWinStation->GetUserName()) != 0) {
SetUserName(pWinStation->GetUserName());
if(pWinStation->HasUser()) SetHasUser();
else ClearHasUser();
bInfoChanged = TRUE;
}
// Check the SdClass
if(m_SdClass != pWinStation->GetSdClass()) {
m_SdClass = pWinStation->GetSdClass();
bInfoChanged = TRUE;
}
// Check the Comment
if(wcscmp(m_Comment, pWinStation->GetComment()) != 0) {
SetComment(pWinStation->GetComment());
bInfoChanged = TRUE;
}
// Check the WdName
if(wcscmp(m_WdName, pWinStation->GetWdName()) != 0) {
SetWdName(pWinStation->GetWdName());
SetWd(pWinStation->GetWd());
bInfoChanged = TRUE;
}
// Check the Encryption Level
if (GetEncryptionLevel() != pWinStation->GetEncryptionLevel() ) {
SetEncryptionLevel(pWinStation->GetEncryptionLevel());
bInfoChanged = TRUE;
}
// Check the Name
if(wcscmp(m_Name, pWinStation->GetName()) != 0) {
SetName(pWinStation->GetName());
bInfoChanged = TRUE;
}
// Check the Client Name
if(wcscmp(m_ClientName, pWinStation->GetClientName()) != 0) {
SetClientName(pWinStation->GetClientName());
bInfoChanged = TRUE;
}
if(wcscmp(m_clientDigProductId, pWinStation->GetClientDigProductId()) != 0) {
SetClientDigProductId(pWinStation->GetClientDigProductId());
bInfoChanged = TRUE;
}
// Always copy the LastInputTime
SetLastInputTime(pWinStation->GetLastInputTime());
// Always copy the CurrentTime
SetCurrentTime(pWinStation->GetCurrentTime());
// Always copy the LogonTime
// (The logon time is not set when we create a CWinStation on the fly)
SetLogonTime(pWinStation->GetLogonTime());
// Always copy the IdleTime
SetIdleTime(pWinStation->GetIdleTime());
// Always copy the Can Shadow flag
if(pWinStation->CanBeShadowed()) SetCanBeShadowed();
// Copy the Extension Info pointer if necessary
if(pWinStation->GetExtensionInfo() && !m_pExtensionInfo) {
m_pExtensionInfo = pWinStation->GetExtensionInfo();
pWinStation->SetExtensionInfo(NULL);
}
// Copy the Extended Info pointer if necessary
if(pWinStation->GetExtendedInfo() && !m_pExtWinStationInfo) {
m_pExtWinStationInfo = pWinStation->GetExtendedInfo();
pWinStation->SetExtendedInfo(NULL);
}
// If this guy hasn't been updated in a while, do it now
if(!bInfoChanged) {
clock_t now = clock();
if((now - GetLastUpdateClock()) > 30)
bInfoChanged = TRUE;
}
if(bInfoChanged) {
SetChanged();
SetLastUpdateClock();
}
return bInfoChanged;
} // end CWinStation::Update
/////////////////////////////////////////////////////////////////////////////
// CWinStation::Connect
//
void CWinStation::Connect(BOOL bUser)
{
TCHAR szPassword[PASSWORD_LENGTH+1];
BOOL bFirstTime = TRUE;
DWORD Error;
HANDLE hServer = m_pServer->GetHandle();
// Start the connect loop with null password to try first.
szPassword[0] = '\0';
while(1) {
if(WinStationConnect(hServer, m_LogonId, LOGONID_CURRENT, szPassword, TRUE))
break; // success - break out of loop
if(((Error = GetLastError()) != ERROR_LOGON_FAILURE) || !bFirstTime ) {
//We need this to know the length of the error message
//now that StandardErrorMessage requires that
CString tempErrorMessage;
tempErrorMessage.LoadString(IDS_ERR_CONNECT);
StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
m_LogonId, Error, tempErrorMessage.GetLength(), 10, IDS_ERR_CONNECT, m_LogonId);
}
// If a 'logon failure' brought us here, issue password dialog.
// Otherwise, break the connect loop.
if(Error == ERROR_LOGON_FAILURE) {
CPasswordDlg CPDlg;
CPDlg.SetDialogMode(bUser ? PwdDlg_UserMode : PwdDlg_WinStationMode);
if(CPDlg.DoModal() == IDOK ) {
lstrcpy(szPassword, CPDlg.GetPassword());
} else {
break; // user CANCEL: break connect loop
}
} else
break; // other error: break connect loop
// the next time through the loop won't be the first
bFirstTime = FALSE;
}
SecureZeroMemory((PVOID)szPassword , sizeof(szPassword));
return;
} // end CWinStation::Connect
/////////////////////////////////////////////////////////////////////////////
// CWinStation::ShowStatus
//
void CWinStation::ShowStatus()
{
switch(m_SdClass) {
case SdNetwork:
case SdNasi:
new CNetworkStatusDlg(this);
break;
case SdAsync:
new CAsyncStatusDlg(this);
break;
default:
break;
}
} // end CWinStation::ShowStatus
/////////////////////////////////////////////////////////////////////////////
// CWinStation::Shadow
//
void CWinStation::Shadow()
{
WINSTATIONCONFIG WSConfig;
SHADOWCLASS Shadow;
ULONG ReturnLength;
DWORD ShadowError;
HANDLE hServer = m_pServer->GetHandle();
// Determine the WinStation's shadow state.
if(!WinStationQueryInformation(hServer,
m_LogonId,
WinStationConfiguration,
&WSConfig, sizeof(WINSTATIONCONFIG),
&ReturnLength ) ) {
// Can't query WinStation configuration; complain and return
return;
}
Shadow = WSConfig.User.Shadow;
// If shadowing is disabled, let the user know and return
if(Shadow == Shadow_Disable ) {
DWORD Error = GetLastError();
//We need this to know the length of the error message
//now that StandardErrorMessage requires that
CString tempErrorMessage;
tempErrorMessage.LoadString(IDS_ERR_SHADOW_DISABLED);
StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
m_LogonId, Error, tempErrorMessage.GetLength(), 10, IDS_ERR_SHADOW_DISABLED, m_LogonId);
return;
}
// If the WinStation is disconnected and shadow notify is 'on',
// let the user know and break out.
if((m_State == State_Disconnected) &&
((Shadow == Shadow_EnableInputNotify) ||
(Shadow == Shadow_EnableNoInputNotify)) ) {
DWORD Error = GetLastError();
//We need this to know the length of the error message
//now that StandardErrorMessage requires that
CString tempErrorMessage;
tempErrorMessage.LoadString(IDS_ERR_SHADOW_DISCONNECTED_NOTIFY_ON);
StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
m_LogonId, Error, tempErrorMessage.GetLength(), 10, IDS_ERR_SHADOW_DISCONNECTED_NOTIFY_ON, m_LogonId);
return;
}
// Display the 'start shadow' dialog for hotkey reminder and
// final 'ok' prior to shadowing.
CShadowStartDlg SSDlg;
SSDlg.m_ShadowHotkeyKey = ((CWinAdminApp*)AfxGetApp())->GetShadowHotkeyKey();
SSDlg.m_ShadowHotkeyShift = ((CWinAdminApp*)AfxGetApp())->GetShadowHotkeyShift();
if(SSDlg.DoModal() != IDOK) {
return;
}
// launch UI thread.
DWORD tid;
HANDLE hThread = ::CreateThread( NULL , 0 , ( LPTHREAD_START_ROUTINE )Shadow_WarningProc , ( LPVOID )AfxGetInstanceHandle() , 0 , &tid );
((CWinAdminApp*)AfxGetApp())->SetShadowHotkeyKey(SSDlg.m_ShadowHotkeyKey);
((CWinAdminApp*)AfxGetApp())->SetShadowHotkeyShift(SSDlg.m_ShadowHotkeyShift);
// Invoke the shadow DLL.
CWaitCursor Nikki;
// allow UI thread to init window
Sleep( 900 );
// Shadow API always connects to local server,
// passing target servername as a parameter.
BOOL bOK = WinStationShadow(SERVERNAME_CURRENT, m_pServer->GetName(), m_LogonId,
(BYTE)((CWinAdminApp*)AfxGetApp())->GetShadowHotkeyKey(),
(WORD)((CWinAdminApp*)AfxGetApp())->GetShadowHotkeyShift());
if (!bOK)
{
ShadowError = GetLastError();
}
if( g_hwndShadowWarn != NULL )
{
OutputDebugString( L"Posting WM_DESTROY to dialog\n");
EndDialog( g_hwndShadowWarn , 0 );
//PostMessage( g_hwndShadowWarn , WM_CLOSEDIALOG , 0 , 0 );
}
if( !bOK )
{
//We need this to know the length of the error message
//now that StandardErrorMessage requires that
CString tempErrorMessage;
tempErrorMessage.LoadString(IDS_ERR_SHADOW);
StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
m_LogonId, ShadowError, tempErrorMessage.GetLength(), 10, IDS_ERR_SHADOW, m_LogonId);
}
CloseHandle( hThread );
} // end CWinStation::Shadow
/////////////////////////////////////////////////////////////////////////////
// CWinStation::SendMessage
//
UINT CWinStation::SendMessage(LPVOID pParam)
{
ASSERT(pParam);
ULONG Response;
UINT RetVal = 0;
((CWinAdminApp*)AfxGetApp())->BeginOutstandingThread();
MessageParms *pMsgParms = (MessageParms*)pParam;
// If we are operating on the current selected Item in the tree it's
// possible that the winstation has disappeared by the time we get here
// so we should just gracefully cleanup
if (pMsgParms->bActionOnCurrentSelection)
{
if (CWinAdminDoc::gm_CurrentSelType != NODE_WINSTATION)
{
goto Cleanup;
}
}
HANDLE hServer = pMsgParms->pWinStation->m_pServer->GetHandle();
if(!WinStationSendMessage(hServer,
pMsgParms->pWinStation->m_LogonId,
pMsgParms->MessageTitle, (wcslen(pMsgParms->MessageTitle)+1)*sizeof(TCHAR),
pMsgParms->MessageBody, (wcslen(pMsgParms->MessageBody)+1)*sizeof(TCHAR),
MB_OK, 60, &Response, TRUE ) ) {
DWORD Error = GetLastError();
//We need this to know the length of the error message
//now that StandardErrorMessage requires that
CString tempErrorMessage;
tempErrorMessage.LoadString(IDS_ERR_MESSAGE);
StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
pMsgParms->pWinStation->m_LogonId, Error, tempErrorMessage.GetLength(),
10, IDS_ERR_MESSAGE, pMsgParms->pWinStation->m_LogonId);
RetVal = 1;
}
Cleanup:
((CWinAdminApp*)AfxGetApp())->EndOutstandingThread();
delete pMsgParms;
return RetVal;
} // end CWinStation::SendMessage
/////////////////////////////////////////////////////////////////////////////
// CWinStation::Disconnect
//
UINT CWinStation::Disconnect(LPVOID pParam)
{
ASSERT(pParam);
UINT RetVal = 0;
HANDLE hServer;
((CWinAdminApp*)AfxGetApp())->BeginOutstandingThread();
DisconnectParms *pDisconnectParms = (DisconnectParms*)pParam;
// If we are operating on the current selected Item in the tree it's
// possible that the winstation has disappeared by the time we get here
// so we should just gracefully cleanup
if (pDisconnectParms->bActionOnCurrentSelection)
{
if (CWinAdminDoc::gm_CurrentSelType != NODE_WINSTATION)
{
goto Cleanup;
}
}
hServer = pDisconnectParms->hServer;
if(!WinStationDisconnect(hServer, pDisconnectParms->ulLogonId, TRUE))
{
DWORD Error = GetLastError();
// We need this to know the length of the error message
// now that StandardErrorMessage requires that
CString tempErrorMessage;
tempErrorMessage.LoadString(IDS_ERR_DISCONNECT);
StandardErrorMessage(AfxGetAppName(),
AfxGetMainWnd()->m_hWnd,
AfxGetInstanceHandle(),
pDisconnectParms->ulLogonId,
Error,
tempErrorMessage.GetLength(),
10,
IDS_ERR_DISCONNECT,
pDisconnectParms->ulLogonId);
RetVal = 1;
}
Cleanup:
((CWinAdminApp*)AfxGetApp())->EndOutstandingThread();
delete pDisconnectParms;
return RetVal;
} // end CWinStation::Disconnect
/////////////////////////////////////////////////////////////////////////////
// CWinStation::Reset
//
UINT CWinStation::Reset(LPVOID pParam)
{
ASSERT(pParam);
UINT RetVal = 0;
((CWinAdminApp*)AfxGetApp())->BeginOutstandingThread();
ResetParms *pResetParms = (ResetParms*)pParam;
// If we are operating on the current selected Item in the tree it's
// possible that the winstation has disappeared by the time we get here
// so we should just gracefully cleanup
if (pResetParms->bActionOnCurrentSelection)
{
if (CWinAdminDoc::gm_CurrentSelType != NODE_WINSTATION)
{
goto Cleanup;
}
}
HANDLE hServer = pResetParms->pWinStation->m_pServer->GetHandle();
if(!WinStationReset(hServer, pResetParms->pWinStation->m_LogonId, TRUE))
{
DWORD Error = GetLastError();
//We need this to know the length of the error message
//now that StandardErrorMessage requires that
CString tempErrorMessage1, tempErrorMessage2;
tempErrorMessage1.LoadString(IDS_ERR_RESET);
tempErrorMessage2.LoadString(IDS_ERR_USER_LOGOFF);
StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
pResetParms->pWinStation->m_LogonId, Error,
pResetParms->bReset ? tempErrorMessage1.GetLength() : tempErrorMessage2.GetLength(), 10,
pResetParms->bReset ? IDS_ERR_RESET : IDS_ERR_USER_LOGOFF, pResetParms->pWinStation->m_LogonId);
RetVal = 1;
}
Cleanup:
((CWinAdminApp*)AfxGetApp())->EndOutstandingThread();
delete pParam;
return RetVal;
} // end CWinStation::Reset
/////////////////////////////////////////////////////////////////////////////
// CWinStation::QueryAdditionalInformation
//
void CWinStation::QueryAdditionalInformation()
{
ULONG ReturnLength;
HANDLE hServer = m_pServer->GetHandle();
WINSTATIONCLIENT ClientData;
// Set all the strings to start with a NULL
m_ClientDir[0] = '\0';
m_ModemName[0] = '\0';
m_ClientLicense[0] = '\0';
m_ClientAddress[0] = '\0';
m_Colors[0] = '\0';
// Set all the values to 0
m_ClientBuildNumber = 0;
m_ClientProductId = 0;
m_HostBuffers = 0;
m_ClientBuffers = 0;
m_BufferLength = 0;
m_ClientSerialNumber = 0;
m_VRes = 0;
m_HRes = 0;
SetAdditionalDone();
if ( WinStationQueryInformation( hServer,
m_LogonId,
WinStationClient,
&ClientData,
sizeof(WINSTATIONCLIENT),
&ReturnLength ) ) {
// Assign string values.
wcscpy(m_ClientDir, ClientData.ClientDirectory);
wcscpy(m_ModemName, ClientData.ClientModem);
wcscpy(m_ClientLicense, ClientData.ClientLicense);
wcscpy(m_ClientAddress, ClientData.ClientAddress);
switch ( ClientData.ColorDepth ) {
case 0x0001:
wcscpy(m_Colors, TEXT("16"));
break;
case 0x0002:
wcscpy(m_Colors, TEXT("256"));
break;
case 0x0004:
wcscpy(m_Colors, TEXT("64K"));
break;
case 0x0008:
wcscpy(m_Colors, TEXT("16M"));
break;
case 0x0010:
wcscpy(m_Colors, TEXT("32M"));
break;
}
// Assign numeric values.
m_ClientBuildNumber = ClientData.ClientBuildNumber;
m_ClientProductId = ClientData.ClientProductId;
m_HostBuffers = ClientData.OutBufCountHost;
m_ClientBuffers = ClientData.OutBufCountClient;
m_BufferLength = ClientData.OutBufLength;
m_ClientSerialNumber = ClientData.SerialNumber;
m_HRes = ClientData.HRes;
m_VRes = ClientData.VRes;
}
// If there is an extension DLL loaded, allow it to add it's own info for this WinStation
LPFNEXWINSTATIONINFOPROC InfoProc = ((CWinAdminApp*)AfxGetApp())->GetExtWinStationInfoProc();
if(InfoProc) {
(*InfoProc)(m_pExtensionInfo, m_State);
}
LPFNEXGETWINSTATIONMODULESPROC ModuleProc = ((CWinAdminApp*)AfxGetApp())->GetExtGetWinStationModulesProc();
if(ModuleProc) {
if(m_pExtModuleInfo) {
// Get the extension DLL's function to free the module info
LPFNEXFREEWINSTATIONMODULESPROC FreeModulesProc = ((CWinAdminApp*)AfxGetApp())->GetExtFreeWinStationModulesProc();
if(FreeModulesProc) {
(*FreeModulesProc)(m_pExtModuleInfo);
} else {
TRACE0("WAExGetWinStationModules exists without WAExFreeWinStationModules\n");
ASSERT(0);
}
}
m_pExtModuleInfo = (*ModuleProc)(GetExtensionInfo(), &m_NumModules);
}
} // end CWinStation::QueryAdditionalInformation
//////////////////////////////////////////////////////////////////////////////////////////
//
// CProcess Member Functions
//
//////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CProcess::CProcess
//
CProcess::CProcess(ULONG PID,
ULONG LogonId,
CServer *pServer,
PSID pSID,
CWinStation *pWinStation,
TCHAR *ImageName)
{
ASSERT(pServer);
DWORD dwImageNameLen;
m_Flags = PF_CURRENT;
m_PID = PID;
m_LogonId = LogonId;
m_pServer = pServer;
m_pWinStation = pWinStation;
m_ImageName = NULL;
if(PID == 0 && !pSID)
{
CString sTemp;
sTemp.LoadString(IDS_SYSTEM_IDLE_PROCESS);
// allocate memory for Image Name and copy to member variable
dwImageNameLen = sTemp.GetLength();
m_ImageName = (LPTSTR)LocalAlloc(LPTR, (dwImageNameLen + 1) * sizeof(TCHAR));
if (m_ImageName != NULL)
{
_tcscpy(m_ImageName, sTemp);
}
SetSystemProcess();
_tcscpy(m_UserName, TEXT("System"));
m_SidCrc = 0;
}
else
{
if(pSID) {
DWORD SidLength = GetLengthSid(pSID);
m_SidCrc = CalculateCrc16((PBYTE)pSID, (USHORT)SidLength);
} else m_SidCrc = 0;
DetermineProcessUser(pSID);
// allocate memory for Image Name and copy to member variable
dwImageNameLen = _tcslen(ImageName);
m_ImageName = (LPTSTR)LocalAlloc(LPTR, (dwImageNameLen + 1) * sizeof(TCHAR));
if (m_ImageName != NULL)
{
_tcscpy(m_ImageName, ImageName);
if(QuerySystemProcess()) SetSystemProcess();
}
}
} // end CProcess::CProcess
TCHAR *SysProcTable[] = {
TEXT("csrss.exe"),
TEXT("smss.exe"),
TEXT("screg.exe"),
TEXT("lsass.exe"),
TEXT("spoolss.exe"),
TEXT("EventLog.exe"),
TEXT("netdde.exe"),
TEXT("clipsrv.exe"),
TEXT("lmsvcs.exe"),
TEXT("MsgSvc.exe"),
TEXT("winlogon.exe"),
TEXT("NETSTRS.EXE"),
TEXT("nddeagnt.exe"),
TEXT("wfshell.exe"),
TEXT("chgcdm.exe"),
TEXT("userinit.exe"),
NULL
};
/////////////////////////////////////////////////////////////////////////////
// CProcess::~CProcess
//
/////////////////////////////////////////////////////////////////////////////
CProcess::~CProcess()
{
if (m_ImageName != NULL)
{
LocalFree(m_ImageName);
}
}
/////////////////////////////////////////////////////////////////////////////
// CProcess::QuerySystemProcess
//
BOOL CProcess::QuerySystemProcess()
{
// First: if the user name is 'system' or no image name is present, treat
// as a 'system' process.
if(!lstrcmpi(m_UserName, TEXT("system")) ||
!(*m_ImageName) )
return TRUE;
// Last: if the image name is one of the well known 'system' images,
// treat it as a 'system' process.
for(int i = 0; SysProcTable[i]; i++)
if(!lstrcmpi( m_ImageName, SysProcTable[i]))
return TRUE;
// Not a 'system' process.
return FALSE;
} // end CProcess::QuerySystemProcess
/////////////////////////////////////////////////////////////////////////////
// CProcess::DetermineProcessUser
//
void CProcess::DetermineProcessUser(PSID pSid)
{
CObList *pUserSidList = m_pServer->GetUserSidList();
// Look for the user Sid in the list
POSITION pos = pUserSidList->GetHeadPosition();
while(pos)
{
CUserSid *pUserSid = (CUserSid*)pUserSidList->GetNext(pos);
if(pUserSid->m_SidCrc == m_SidCrc)
{
wcscpy(m_UserName, pUserSid->m_UserName);
return;
}
}
// It wasn't in the list
// Get the user from the Sid and put it in our list
GetUserFromSid(pSid, m_UserName, USERNAME_LENGTH);
if (!lstrcmpi(m_UserName,TEXT("system")))
{
wcscpy(m_UserName, TEXT("System")); // to make the UI guys happy
}
CUserSid *pUserSid = new CUserSid;
if(pUserSid == NULL)
{
return;
}
pUserSid->m_SidCrc = m_SidCrc;
memset(pUserSid->m_UserName, 0, sizeof(pUserSid->m_UserName));
lstrcpy(pUserSid->m_UserName, m_UserName);
pUserSidList->AddTail(pUserSid);
} // end CProcess::DetermineProcessUser
/////////////////////////////////////////////////////////////////////////////
// CProcess::Update
//
BOOL CProcess::Update(CProcess *pProcess)
{
ASSERT(pProcess);
BOOL bChanged = FALSE;
// Check the WinStation
if(m_pWinStation != pProcess->GetWinStation())
{
m_pWinStation = pProcess->GetWinStation();
bChanged = TRUE;
}
else
{
if(m_pWinStation->IsChanged())
{
bChanged = TRUE;
}
}
if(bChanged) SetChanged();
return bChanged;
} // end CProcess::Update
//////////////////////////////////////////////////////////////////////////////////////////
//
// CLicense Member Functions
//
//////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CLicense::CLicense
//
CLicense::CLicense(CServer *pServer, ExtLicenseInfo *pLicenseInfo)
{
ASSERT(pServer);
ASSERT(pLicenseInfo);
m_pServer = pServer;
m_Class = pLicenseInfo->Class;
m_PoolLicenseCount = pLicenseInfo->PoolLicenseCount;
m_LicenseCount = pLicenseInfo->LicenseCount;
m_Flags = pLicenseInfo->Flags;
wcscpy(m_RegSerialNumber, pLicenseInfo->RegSerialNumber);
wcscpy(m_LicenseNumber, pLicenseInfo->LicenseNumber);
wcscpy(m_Description, pLicenseInfo->Description);
// Figure out the pooling count
if(m_Flags & ELF_POOLING)
m_PoolCount = m_PoolLicenseCount;
else m_PoolCount = 0xFFFFFFFF;
} // end CLicense::CLicense
//////////////////////////////////////////////////////////////////////////////////////////
//
// CWd Member Functions
//
//////////////////////////////////////////////////////////////////////////////////////////
static CHAR szEncryptionLevels[] = "ExtEncryptionLevels";
/////////////////////////////////////////////////////////////////////////////
// CWd::CWd
//
CWd::CWd(PWDCONFIG2 pWdConfig, PWDNAME pRegistryName)
{
m_pEncryptionLevels = NULL;
m_NumEncryptionLevels = 0L;
wcscpy(m_WdName, pWdConfig->Wd.WdName);
wcscpy(m_RegistryName, pRegistryName);
// Load the extension DLL for this WD
m_hExtensionDLL = ::LoadLibrary(pWdConfig->Wd.CfgDLL);
if(m_hExtensionDLL) {
// Get the entry points
m_lpfnExtEncryptionLevels = (LPFNEXTENCRYPTIONLEVELSPROC)::GetProcAddress(m_hExtensionDLL, szEncryptionLevels);
if(m_lpfnExtEncryptionLevels) {
m_NumEncryptionLevels = (*m_lpfnExtEncryptionLevels)(NULL, &m_pEncryptionLevels);
}
}
} // end CWd::CWd
/////////////////////////////////////////////////////////////////////////////
// CWd::~CWd
//
CWd::~CWd()
{
if(m_hExtensionDLL) {
::FreeLibrary(m_hExtensionDLL);
}
} // end CWd::~CWd
/////////////////////////////////////////////////////////////////////////////
// CWd::GetEncryptionLevelString
//
BOOL CWd::GetEncryptionLevelString(DWORD Value, CString *pString)
{
if(!m_NumEncryptionLevels) return FALSE;
for(LONG i = 0; i < m_NumEncryptionLevels; i++) {
// Is this the right encryption level
if(Value == m_pEncryptionLevels[i].RegistryValue) {
TCHAR estring[128];
if(::LoadString(m_hExtensionDLL,
m_pEncryptionLevels[i].StringID, estring, 127)) {
pString->Format(TEXT("%s"), estring);
return TRUE;
}
return FALSE;
}
}
return FALSE;
} // end CWd::GetEncryptionLevelString
//------------------------------------------------
DWORD Shadow_WarningProc( LPVOID param )
{
HINSTANCE hInst = ( HINSTANCE )param;
OutputDebugString( L"Shadow_WarningProc called\n" );
DialogBox( hInst , MAKEINTRESOURCE( IDD_DIALOG_SHADOWWARN ) , NULL , ShadowWarn_WndProc );
OutputDebugString( L"Shadow_WarningProc exiting thread\n" );
ExitThread( 0 );
return 0;
}
//------------------------------------------------
INT_PTR CALLBACK ShadowWarn_WndProc( HWND hwnd , UINT msg , WPARAM wp , LPARAM lp )
{
switch( msg )
{
case WM_INITDIALOG:
g_hwndShadowWarn = hwnd;
OutputDebugString( L"WM_INITDIALOG -- in ShadowWarn_WndProc\n" );
CenterDlg( GetDesktopWindow( ) , hwnd );
break;
case WM_CLOSE:
EndDialog( hwnd , 0 );
break;
}
return FALSE;
}
void CenterDlg(HWND hwndToCenterOn , HWND hDlg )
{
RECT rc, rcwk, rcToCenterOn;
SetRect( &rcToCenterOn , 0 , 0 , GetSystemMetrics(SM_CXSCREEN) , GetSystemMetrics( SM_CYSCREEN ) );
if (hwndToCenterOn != NULL)
{
::GetWindowRect(hwndToCenterOn, &rcToCenterOn);
}
::GetWindowRect( hDlg , &rc);
UINT uiWidth = rc.right - rc.left;
UINT uiHeight = rc.bottom - rc.top;
rc.left = (rcToCenterOn.left + rcToCenterOn.right) / 2 - ( rc.right - rc.left ) / 2;
rc.top = (rcToCenterOn.top + rcToCenterOn.bottom) / 2 - ( rc.bottom - rc.top ) / 2;
//ensure the dialog always with the work area
if(SystemParametersInfo(SPI_GETWORKAREA, 0, &rcwk, 0))
{
UINT wkWidth = rcwk.right - rcwk.left;
UINT wkHeight = rcwk.bottom - rcwk.top;
if(rc.left + uiWidth > wkWidth) //right cut
rc.left = wkWidth - uiWidth;
if(rc.top + uiHeight > wkHeight) //bottom cut
rc.top = wkHeight - uiHeight;
if(rc.left < rcwk.left) //left cut
rc.left += rcwk.left - rc.left;
if(rc.top < rcwk.top) //top cut
rc.top += rcwk.top - rc.top;
}
::SetWindowPos( hDlg, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER |
SWP_NOCOPYBITS | SWP_DRAWFRAME);
}