/******************************************************************************* * * 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 // for alloca used by Unicode conversion macros #include // for Unicode conversion macros static int _convert; #include #include #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; #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_pProcessThread = 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; wcscpy(m_pDefaultExtServerInfo->TcpAddress, NAString); wcscpy(m_pDefaultExtServerInfo->IpxAddress, NAString); 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. if( m_pProcessThread != NULL ) { ShutdownMessage(IDS_SHUTDOWN_PROCTHREAD, pDlg); m_ProcessContinue = FALSE; // Fire off the event to wake him up if he is // waiting m_ProcessWakeUpEvent.SetEvent(); HANDLE hThread = m_pProcessThread->m_hThread; if( WaitForSingleObject(hThread, 1000) == WAIT_TIMEOUT ) { TerminateThread(hThread, 0); } WaitForSingleObject(hThread, INFINITE); } 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 m_pProcessThread = AfxBeginThread((AFX_THREADPROC)CWinAdminDoc::ProcessThreadProc, this); 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 // UINT 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 *p = (CFrameWnd*)pDoc->GetMainWnd(); if(p && ::IsWindow(p->GetSafeHwnd())) p->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(); POSITION 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 *pDomain = new CDomain( pszDN ); if( pDomain != NULL ) { AddDomain( pDomain ); } 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 ) { LPTSTR 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; 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) { pParms->pWinStation = (CWinStation*)m_pTempSelectedNode; AfxBeginThread((AFX_THREADPROC)CWinStation::SendMessage, pParms); } return; } // Is the WinStation selected in the tree? if(m_CurrentSelectedType == NODE_WINSTATION) { pParms->pWinStation = (CWinStation*)m_CurrentSelectedNode; 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; 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; 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) { // 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) { AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, (CWinStation*)m_pTempSelectedNode); } return; } if(m_CurrentSelectedType == NODE_WINSTATION) { AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, (CWinStation*)m_CurrentSelectedNode); } // 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()) { // Start a thread to do the disconnect AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, pWinStation); } } // 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()) { // Start a thread to do the disconnect AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, pWinStation); } } // 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) { // create a reset parameters structure ResetParms *pResetParms = new ResetParms; if(pResetParms) { pResetParms->pWinStation = (CWinStation*)m_pTempSelectedNode; pResetParms->bReset = bReset; 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; 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; // 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; // 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( ) ) { 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( ) ) { 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 (((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() && !pWinStation->IsSystemConsole()) 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() && !pWinStation->IsSystemConsole()) 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) { 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; } 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; 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; } delete pMsgParms; ((CWinAdminApp*)AfxGetApp())->EndOutstandingThread(); return RetVal; } // end CWinStation::SendMessage ///////////////////////////////////////////////////////////////////////////// // CWinStation::Disconnect // UINT CWinStation::Disconnect(LPVOID pParam) { ASSERT(pParam); UINT RetVal = 0; ((CWinAdminApp*)AfxGetApp())->BeginOutstandingThread(); CWinStation *pWinStation = (CWinStation*)pParam; HANDLE hServer = pWinStation->m_pServer->GetHandle(); if(!WinStationDisconnect(hServer, pWinStation->m_LogonId, 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(), pWinStation->m_LogonId, Error, tempErrorMessage.GetLength(), 10, IDS_ERR_DISCONNECT, pWinStation->m_LogonId); RetVal = 1; } ((CWinAdminApp*)AfxGetApp())->EndOutstandingThread(); return RetVal; } // end CWinStation::Disconnect ///////////////////////////////////////////////////////////////////////////// // CWinStation::Reset // UINT CWinStation::Reset(LPVOID pParam) { ASSERT(pParam); UINT RetVal = 0; ((CWinAdminApp*)AfxGetApp())->BeginOutstandingThread(); ResetParms *pResetParms = (ResetParms*)pParam; 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; } ((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); m_Flags = PF_CURRENT; m_PID = PID; m_LogonId = LogonId; m_pServer = pServer; m_pWinStation = pWinStation; wcscpy(m_ImageName, ImageName); if(PID == 0 && !pSID) { CString sTemp; sTemp.LoadString(IDS_SYSTEM_IDLE_PROCESS); wcscpy(m_ImageName, sTemp); SetSystemProcess(); wcscpy(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); 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::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) { 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); }