Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4569 lines
148 KiB

  1. /*******************************************************************************
  2. *
  3. * admindoc.cpp
  4. *
  5. * implementation of the CWinAdminDoc class
  6. *
  7. * copyright notice: Copyright 1997, Citrix Systems Inc.
  8. * Copyright (c) 1998 - 1999 Microsoft Corporation
  9. *
  10. * $Author: donm $ Don Messerli
  11. *
  12. * $Log: N:\nt\private\utils\citrix\winutils\tsadmin\VCS\admindoc.cpp $
  13. *
  14. * Rev 1.15 25 Apr 1998 13:43:08 donm
  15. * MS 2167: try to use proper Wd from registry
  16. *
  17. * Rev 1.14 19 Feb 1998 17:39:28 donm
  18. * removed latest extension DLL support
  19. *
  20. * Rev 1.12 19 Jan 1998 16:45:28 donm
  21. * new ui behavior for domains and servers
  22. *
  23. * Rev 1.11 13 Nov 1997 13:18:46 donm
  24. * removed check for ICA for shadowing
  25. *
  26. * Rev 1.10 07 Nov 1997 23:05:58 donm
  27. * fixed inability to logoff/reset
  28. * Rev 1.0 30 Jul 1997 17:10:10 butchd
  29. * Initial revision.
  30. *
  31. *******************************************************************************/
  32. #include "stdafx.h"
  33. #include "winadmin.h"
  34. #include "admindoc.h"
  35. #include "dialogs.h"
  36. #include <malloc.h> // for alloca used by Unicode conversion macros
  37. #include <mfc42\afxconv.h> // for Unicode conversion macros
  38. static int _convert;
  39. #include <winsta.h>
  40. #include <regapi.h>
  41. #include "..\..\inc\utilsub.h"
  42. #ifdef _DEBUG
  43. #define new DEBUG_NEW
  44. #undef THIS_FILE
  45. static char THIS_FILE[] = __FILE__;
  46. #endif
  47. #ifdef _STRESS_BUILD
  48. extern BOOL g_fWaitForAllServersToDisconnect;
  49. #endif
  50. DWORD Shadow_WarningProc( LPVOID param );
  51. INT_PTR CALLBACK ShadowWarn_WndProc( HWND , UINT , WPARAM , LPARAM );
  52. void CenterDlg(HWND hwndToCenterOn , HWND hDlg );
  53. HWND g_hwndShadowWarn = NULL;
  54. DWORD g_dwTreeViewExpandedStates;
  55. // Initialize static variable
  56. NODETYPE CWinAdminDoc::gm_CurrentSelType = NODE_NONE;
  57. #define WM_SETTHEEVENT ( WM_USER + 755 )
  58. // Sort order for Connect States
  59. ULONG SortOrder[] =
  60. {
  61. 3, //State_Active user logged on to WinStation
  62. 2, //State_Connected WinStation connected to client
  63. 0, //State_ConnectQuery in the process of connecting to client
  64. 5, //State_Shadow shadowing another WinStation
  65. 4, //State_Disconnected WinStation logged on without client
  66. 6, //State_Idle waiting for client to connect
  67. 1, //State_Listen WinStation is listening for connection
  68. 9, //State_Reset WinStation is being reset
  69. 7, //State_Down WinStation is down due to error
  70. 8 //State_Init WinStation in initialization
  71. };
  72. /////////////////////////////////////////////////////////////////////////////
  73. // CWinAdminDoc
  74. IMPLEMENT_DYNCREATE(CWinAdminDoc, CDocument)
  75. BEGIN_MESSAGE_MAP(CWinAdminDoc, CDocument)
  76. //{{AFX_MSG_MAP(CWinAdminDoc)
  77. // NOTE - the ClassWizard will add and remove mapping macros here.
  78. // DO NOT EDIT what you see in these blocks of generated code!
  79. //}}AFX_MSG_MAP
  80. END_MESSAGE_MAP()
  81. BOOL CWinAdminDoc::m_ProcessContinue = TRUE;
  82. /////////////////////////////////////////////////////////////////////////////
  83. // CWinAdminDoc constructor
  84. //
  85. CWinAdminDoc::CWinAdminDoc()
  86. {
  87. // TODO: add one-time construction code here
  88. m_CurrentSelectedNode = NULL;
  89. m_CurrentSelectedType = NODE_NONE;
  90. m_pTempSelectedNode = NULL;
  91. m_TempSelectedType = NODE_NONE;
  92. m_AllViewsReady = FALSE;
  93. m_hProcessThread = NULL;
  94. m_pCurrentDomain = NULL;
  95. m_pCurrentServer = NULL;
  96. m_pPersistentConnections = NULL;
  97. m_InRefresh = FALSE;
  98. m_bInShutdown = FALSE;
  99. m_UnknownString = ::GetUnknownString();
  100. ASSERT( m_UnknownString != NULL );
  101. ((CWinAdminApp*)AfxGetApp())->SetDocument(this);
  102. // If there is an extension DLL, get a pointer to it's global
  103. // info structure
  104. LPFNEXGETGLOBALINFOPROC InfoProc = ((CWinAdminApp*)AfxGetApp())->GetExtGetGlobalInfoProc();
  105. if(InfoProc)
  106. {
  107. m_pExtGlobalInfo = (*InfoProc)();
  108. }
  109. else
  110. {
  111. m_pExtGlobalInfo = NULL;
  112. }
  113. // create the default extended server info
  114. // for servers that haven't had their extended info
  115. // created yet
  116. m_pDefaultExtServerInfo = new ExtServerInfo;
  117. CString NAString;
  118. NAString.LoadString(IDS_NOT_APPLICABLE);
  119. memset(m_pDefaultExtServerInfo, 0, sizeof(ExtServerInfo));
  120. // This is so the N/A TcpAddresses will sort at the end
  121. m_pDefaultExtServerInfo->RawTcpAddress = 0xFFFFFFFF;
  122. m_pDefaultExtServerInfo->ServerTotalInUse = 0xFFFFFFFF;
  123. lstrcpyn(m_pDefaultExtServerInfo->TcpAddress, NAString, sizeof(m_pDefaultExtServerInfo->TcpAddress) / sizeof(TCHAR));
  124. lstrcpyn(m_pDefaultExtServerInfo->IpxAddress, NAString, sizeof(m_pDefaultExtServerInfo->IpxAddress) / sizeof(TCHAR));
  125. m_focusstate = TREE_VIEW;
  126. m_prevFocusState = TAB_CTRL;
  127. m_fOnTab = FALSE;
  128. m_pszFavList = NULL;
  129. } // end CWinAdminDoc::CWinAdminDoc
  130. /////////////////////////////////////////////////////////////////////////////
  131. // CWinAdminDoc destructor
  132. //
  133. CWinAdminDoc::~CWinAdminDoc()
  134. {
  135. // all code moved to Shutdown();
  136. delete m_pDefaultExtServerInfo;
  137. if(m_pPersistentConnections) LocalFree(m_pPersistentConnections);
  138. if( m_UnknownString != NULL )
  139. {
  140. LocalFree( ( PVOID )m_UnknownString );
  141. }
  142. } // end CWinAdminDoc::~CWinAdminDoc
  143. /////////////////////////////////////////////////////////////////////////////
  144. // CWinAdminDoc::ShutdownMessage
  145. //
  146. void CWinAdminDoc::ShutdownMessage(UINT id, CDialog *pDlg)
  147. {
  148. ASSERT(pDlg);
  149. CString AString;
  150. AString.LoadString(id);
  151. pDlg->SetDlgItemText(IDC_SHUTDOWN_MSG, AString);
  152. } // end CWinAdminDoc::ShutdownMessage
  153. /////////////////////////////////////////////////////////////////////////////
  154. // CWinAdminDoc::Shutdown
  155. //
  156. void CWinAdminDoc::Shutdown(CDialog *pDlg)
  157. {
  158. ASSERT(pDlg);
  159. m_bInShutdown = TRUE;
  160. // Iterate through the domain list
  161. POSITION pos = m_DomainList.GetHeadPosition();
  162. ShutdownMessage(IDS_SHUTDOWN_DOMAINTHREADS, pDlg);
  163. while(pos) {
  164. // Go to the next domain in the list
  165. CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
  166. pDomain->ClearBackgroundContinue();
  167. // Fire off the event to wake him up if he is
  168. // waiting
  169. pDomain->SetEnumEvent();
  170. }
  171. pos = m_DomainList.GetHeadPosition();
  172. while(pos) {
  173. // Go to the next domain in the list
  174. CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
  175. pDomain->StopEnumerating();
  176. }
  177. // Tell the process thread to terminate and wait for it to do so
  178. // make sure the process thread is still running first
  179. DWORD dwThreadExitCode;
  180. GetExitCodeThread(m_hProcessThread, &dwThreadExitCode);
  181. if (dwThreadExitCode == STILL_ACTIVE)
  182. {
  183. ShutdownMessage(IDS_SHUTDOWN_PROCTHREAD, pDlg);
  184. m_ProcessContinue = FALSE;
  185. // fire off the event to wake him up if he is waiting
  186. m_ProcessWakeUpEvent.SetEvent();
  187. // wait until the thread is finished
  188. WaitForSingleObject(m_hProcessThread, INFINITE);
  189. // we're done with our process thread so we can close the handle
  190. CloseHandle(m_hProcessThread);
  191. }
  192. ShutdownMessage(IDS_SHUTDOWN_PREFS, pDlg);
  193. WritePreferences();
  194. LockServerList();
  195. ShutdownMessage(IDS_SHUTDOWN_NOTIFY, pDlg);
  196. // First, tell all the server background threads to stop.
  197. // We do this before the destructor for each server does it
  198. // so that the background threads for all the servers can stop
  199. // and we don't have to wait until we get to the destructor for
  200. // each server
  201. pos = m_ServerList.GetHeadPosition();
  202. while(pos)
  203. {
  204. // Go to the next server in the list
  205. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  206. pServer->ClearBackgroundContinue();
  207. }
  208. // Iterate through the server list
  209. pos = m_ServerList.GetHeadPosition();
  210. while(pos) {
  211. // Go to the next server in the list
  212. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  213. if(pServer->IsState(SS_GOOD)) {
  214. CString AString;
  215. AString.Format(IDS_DISCONNECTING, pServer->GetName());
  216. pDlg->SetDlgItemText(IDC_SHUTDOWN_MSG, AString);
  217. }
  218. pServer->Disconnect( );
  219. delete pServer;
  220. }
  221. m_ServerList.RemoveAll();
  222. UnlockServerList();
  223. // Iterate through the domain list
  224. pos = m_DomainList.GetHeadPosition();
  225. while(pos) {
  226. // Go to the next domain in the list
  227. CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
  228. delete pDomain;
  229. }
  230. m_DomainList.RemoveAll();
  231. // If there is an extension DLL, call it's shutdown function
  232. LPFNEXSHUTDOWNPROC ShutdownProc = ((CWinAdminApp*)AfxGetApp())->GetExtShutdownProc();
  233. if(ShutdownProc) {
  234. (*ShutdownProc)();
  235. }
  236. // Iterate through the Wd list
  237. LockWdList();
  238. pos = m_WdList.GetHeadPosition();
  239. while(pos) {
  240. // Go to the next Wd in the list
  241. CWd *pWd = (CWd*)m_WdList.GetNext(pos);
  242. delete pWd;
  243. }
  244. m_WdList.RemoveAll();
  245. UnlockWdList();
  246. ShutdownMessage(IDS_DONE, pDlg);
  247. } // end CWinAdminDoc::Shutdown
  248. /////////////////////////////////////////////////////////////////////////////
  249. // CWinAdminDoc::CanCloseFrame
  250. //
  251. BOOL CWinAdminDoc::CanCloseFrame(CFrameWnd *pFW)
  252. {
  253. ASSERT(pFW);
  254. CWaitCursor Nikki;
  255. CDialog dlgWait;
  256. dlgWait.Create(IDD_SHUTDOWN, pFW);
  257. Shutdown(&dlgWait);
  258. dlgWait.PostMessage(WM_CLOSE);
  259. return TRUE;
  260. } // end CWinAdminDoc::CanCloseFrame
  261. /////////////////////////////////////////////////////////////////////////////
  262. // CWinAdminDoc::OnNewDocument
  263. //
  264. BOOL CWinAdminDoc::OnNewDocument()
  265. {
  266. if (!CDocument::OnNewDocument())
  267. return FALSE;
  268. // TODO: add reinitialization code here
  269. // (SDI documents will reuse this document)
  270. ReadPreferences();
  271. BuildWdList();
  272. BuildDomainList();
  273. // Create a pServer object for the Server we are running on, this will give
  274. // him a headstart in getting his information
  275. CServer *pServer = new CServer(m_pCurrentDomain, ((CWinAdminApp*)AfxGetApp())->GetCurrentServerName(), FALSE, TRUE);
  276. m_pCurrentServer = pServer;
  277. if( pServer )
  278. {
  279. AddServer(pServer);
  280. }
  281. // Start enumerating servers in the current domain
  282. // if(m_pCurrentDomain) m_pCurrentDomain->StartEnumerating();
  283. // Start the background thread to enumerate processes
  284. DWORD dwThreadID;
  285. m_hProcessThread = CreateThread(NULL, // default security attributes
  286. 0, // default stack size
  287. CWinAdminDoc::ProcessThreadProc,
  288. this, // param passed into threadProc
  289. 0, // default creation flags
  290. &dwThreadID);
  291. // make sure our thread created by ensuring the handle is non null
  292. if (!m_hProcessThread)
  293. {
  294. return FALSE;
  295. }
  296. return TRUE;
  297. } // end CWinAdminDoc::OnNewDocument
  298. /////////////////////////////////////////////////////////////////////////////
  299. // CWinAdminDoc serialization
  300. //
  301. void CWinAdminDoc::Serialize(CArchive& ar)
  302. {
  303. if (ar.IsStoring())
  304. {
  305. // TODO: add storing code here
  306. }
  307. else
  308. {
  309. // TODO: add loading code here
  310. }
  311. } // end CWinAdminDoc::Serialize
  312. /////////////////////////////////////////////////////////////////////////////
  313. // CWinAdminDoc diagnostics
  314. //
  315. #ifdef _DEBUG
  316. void CWinAdminDoc::AssertValid() const
  317. {
  318. CDocument::AssertValid();
  319. }
  320. void CWinAdminDoc::Dump(CDumpContext& dc) const
  321. {
  322. CDocument::Dump(dc);
  323. }
  324. #endif //_DEBUG
  325. /////////////////////////////////////////////////////////////////////////////
  326. // CWinAdminDoc::ShouldConnect
  327. //
  328. // Returns TRUE if the server is in the list of persistent connections
  329. //
  330. BOOL CWinAdminDoc::ShouldConnect(LPWSTR pServerName)
  331. {
  332. ASSERT(pServerName);
  333. if(m_ConnectionsPersistent && m_pPersistentConnections)
  334. {
  335. LPWSTR pTemp = m_pPersistentConnections;
  336. while(*pTemp)
  337. {
  338. if( !wcscmp( pTemp , pServerName ) )
  339. {
  340. return TRUE;
  341. }
  342. // Go to the next server in the buffer
  343. pTemp += (wcslen(pTemp) + 1);
  344. }
  345. }
  346. return FALSE;
  347. }
  348. //=-------------------------------------------------------------------
  349. BOOL CWinAdminDoc::ShouldAddToFav( LPTSTR pServerName )
  350. {
  351. ODS( L"CWinAdminDoc::ShouldAddToFav\n" );
  352. if( m_pszFavList != NULL )
  353. {
  354. LPTSTR pszTemp = m_pszFavList;
  355. while(*pszTemp)
  356. {
  357. if( !wcscmp( pszTemp , pServerName ) )
  358. {
  359. DBGMSG( L"Adding %s to favorites\n" , pszTemp );
  360. return TRUE;
  361. }
  362. // Go to the next server in the buffer
  363. pszTemp += ( wcslen( pszTemp ) + 1 );
  364. }
  365. }
  366. return FALSE;
  367. }
  368. /////////////////////////////////////////////////////////////////////////////
  369. // CWinAdminDoc::ProcessThreadProc
  370. //
  371. // Static member function for process thread
  372. // Called with AfxBeginThread
  373. // Thread terminates when function returns
  374. //
  375. DWORD WINAPI CWinAdminDoc::ProcessThreadProc(LPVOID _doc)
  376. {
  377. ASSERT(_doc);
  378. // We need a pointer to the document so we can make
  379. // calls to member functions
  380. CWinAdminDoc *pDoc = (CWinAdminDoc*)_doc;
  381. // We can't send messages to the view until they're ready
  382. while(!pDoc->AreAllViewsReady()) Sleep(500);
  383. pDoc->AddToFavoritesNow( );
  384. CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
  385. if( p != NULL )
  386. {
  387. p->SendMessage( WM_ADMIN_UPDATE_TVSTATE , 0 , 0 );
  388. }
  389. while(1) {
  390. // We don't want to do this constantly, it eats up processor cycles
  391. // Document destructor will signal the event to wake us up if he
  392. // wants us to quit
  393. pDoc->m_ProcessWakeUpEvent.Lock(((CWinAdminApp*)AfxGetApp())->GetProcessListRefreshTime());
  394. // Make sure we don't have to quit
  395. if(!ShouldProcessContinue()) return 0;
  396. // We only want to enumerate processes if the page is VIEW_SERVER or VIEW_WINSTATION
  397. if(pDoc->GetCurrentView() == VIEW_SERVER || pDoc->GetCurrentView() == VIEW_WINSTATION) {
  398. CServer *pServer = (pDoc->GetCurrentView() == VIEW_SERVER) ? (CServer*)pDoc->GetCurrentSelectedNode()
  399. : (CServer*)((CWinStation*)pDoc->GetCurrentSelectedNode())->GetServer();
  400. // Enumerate processes for this server if his state is SS_GOOD
  401. if(pServer->IsState(SS_GOOD)) {
  402. pServer->EnumerateProcesses();
  403. }
  404. // Make sure we don't have to quit
  405. if(!ShouldProcessContinue()) return 0;
  406. // We only want to send a message to update the view if the
  407. // view is still VEIW_SERVER/VIEW_WINSTATION and the currently
  408. // selected Server is the same one that we just enumerate processes for
  409. if((pDoc->GetCurrentView() == VIEW_SERVER && pServer == (CServer*)pDoc->GetCurrentSelectedNode())
  410. || (pDoc->GetCurrentView() == VIEW_WINSTATION && pServer == (CServer*)((CWinStation*)pDoc->GetCurrentSelectedNode())->GetServer())) {
  411. CFrameWnd *pWnd = (CFrameWnd*)pDoc->GetMainWnd();
  412. if(pWnd && ::IsWindow(pWnd->GetSafeHwnd())) pWnd->SendMessage(WM_ADMIN_UPDATE_PROCESSES, 0, (LPARAM)pServer);
  413. }
  414. }
  415. // Make sure we don't have to quit
  416. if(!ShouldProcessContinue()) return 0;
  417. }
  418. return 0;
  419. } // end CWinAdminDoc::ProcessThreadProc
  420. /////////////////////////////////////////////////////////////////////////////
  421. // CWinAdminDoc::UpdateAllProcesses
  422. //
  423. void CWinAdminDoc::UpdateAllProcesses()
  424. {
  425. LockServerList();
  426. POSITION pos = m_ServerList.GetHeadPosition();
  427. while(pos) {
  428. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  429. // Enumerate processes for this server if his state is SS_GOOD
  430. if(pServer->IsState(SS_GOOD)) {
  431. pServer->EnumerateProcesses();
  432. // Send a message to the view to update this server's processes
  433. CFrameWnd *p = (CFrameWnd*)GetMainWnd();
  434. if(p && ::IsWindow(p->GetSafeHwnd())) p->SendMessage(WM_ADMIN_UPDATE_PROCESSES, 0, (LPARAM)pServer);
  435. }
  436. }
  437. UnlockServerList();
  438. } // end CWinAdminDoc::UpdateAllProcesses
  439. static TCHAR szWinAdminAppKey[] = REG_SOFTWARE_TSERVER TEXT("\\TSADMIN");
  440. static TCHAR szConnectionsPersistent[] = TEXT("ConnectionsPersistent");
  441. static TCHAR szFavList[] = TEXT("Favorites" );
  442. static TCHAR szTVStates[] = TEXT( "TreeViewStates" );
  443. static TCHAR szConnections[] = TEXT("Connections");
  444. /////////////////////////////////////////////////////////////////////////////
  445. // CWinAdminDoc::ReadPreferences
  446. //
  447. // Read user preferences
  448. //
  449. void CWinAdminDoc::ReadPreferences()
  450. {
  451. HKEY hKeyWinAdmin;
  452. DWORD dwType, cbData, dwValue;
  453. // Set to defaults
  454. m_ConnectionsPersistent = FALSE;
  455. // Open registry key for our application
  456. DWORD Disposition;
  457. if( RegCreateKeyEx( HKEY_CURRENT_USER ,
  458. szWinAdminAppKey,
  459. 0,
  460. TEXT(""),
  461. REG_OPTION_NON_VOLATILE,
  462. KEY_READ,
  463. NULL,
  464. &hKeyWinAdmin,
  465. &Disposition) != ERROR_SUCCESS )
  466. {
  467. return;
  468. }
  469. // Read the favorites list
  470. DWORD dwLen = 0;
  471. dwType = 0;
  472. // See how big the multi-string is
  473. int err = RegQueryValueEx( hKeyWinAdmin,
  474. szFavList,
  475. NULL,
  476. &dwType,
  477. NULL,
  478. &dwLen );
  479. if( err == ERROR_SUCCESS || err == ERROR_BUFFER_OVERFLOW )
  480. {
  481. m_pszFavList = ( LPWSTR )LocalAlloc( 0 , dwLen );
  482. if( m_pszFavList != NULL )
  483. {
  484. memset( m_pszFavList , 0 , dwLen );
  485. RegQueryValueEx( hKeyWinAdmin,
  486. szFavList,
  487. NULL,
  488. &dwType,
  489. (LPBYTE)m_pszFavList,
  490. &dwLen);
  491. }
  492. }
  493. // Read the Connections Persist preference
  494. cbData = sizeof( m_ConnectionsPersistent );
  495. if( RegQueryValueEx( hKeyWinAdmin ,
  496. szConnectionsPersistent ,
  497. NULL,
  498. &dwType,
  499. (LPBYTE)&dwValue,
  500. &cbData) == ERROR_SUCCESS)
  501. {
  502. m_ConnectionsPersistent = dwValue;
  503. }
  504. // If connections are persistent, read the list of connections saved
  505. if( m_ConnectionsPersistent )
  506. {
  507. dwLen = 0;
  508. dwType = 0;
  509. // See how big the multi-string is
  510. err = RegQueryValueEx( hKeyWinAdmin,
  511. szConnections,
  512. NULL,
  513. &dwType,
  514. NULL,
  515. &dwLen );
  516. if(err && (err != ERROR_BUFFER_OVERFLOW) )
  517. {
  518. RegCloseKey(hKeyWinAdmin);
  519. return;
  520. }
  521. m_pPersistentConnections = (LPWSTR)LocalAlloc(0, dwLen);
  522. if( m_pPersistentConnections != NULL )
  523. {
  524. memset(m_pPersistentConnections, 0, dwLen);
  525. RegQueryValueEx( hKeyWinAdmin,
  526. szConnections,
  527. NULL,
  528. &dwType,
  529. (LPBYTE)m_pPersistentConnections,
  530. &dwLen);
  531. }
  532. }
  533. g_dwTreeViewExpandedStates = 0;
  534. dwLen = sizeof( g_dwTreeViewExpandedStates );
  535. RegQueryValueEx( hKeyWinAdmin ,
  536. szTVStates,
  537. NULL,
  538. &dwType,
  539. ( LPBYTE )&g_dwTreeViewExpandedStates,
  540. &dwLen );
  541. RegCloseKey(hKeyWinAdmin);
  542. } // end CWinAdminDoc::ReadPreferences
  543. /////////////////////////////////////////////////////////////////////////////
  544. // CWinAdminDoc::WritePreferences
  545. //
  546. // Write user preferences
  547. //
  548. void CWinAdminDoc::WritePreferences()
  549. {
  550. HKEY hKeyWinAdmin;
  551. DWORD dwValue;
  552. // Open registry key for our application
  553. DWORD Disposition;
  554. if( RegCreateKeyEx( HKEY_CURRENT_USER,
  555. szWinAdminAppKey,
  556. 0,
  557. TEXT(""),
  558. REG_OPTION_NON_VOLATILE,
  559. KEY_WRITE,
  560. NULL,
  561. &hKeyWinAdmin,
  562. &Disposition) != ERROR_SUCCESS )
  563. {
  564. return;
  565. }
  566. // Write the servers that are in the favorite list
  567. DWORD dwByteCount = 0;
  568. LockServerList();
  569. POSITION pos = m_ServerList.GetHeadPosition();
  570. #ifdef _STRESS_BUILD
  571. int nStressServerLimit = 0;
  572. #endif;
  573. while(pos)
  574. {
  575. #ifdef _STRESS_BUILD
  576. if( nStressServerLimit >= 10000 )
  577. {
  578. break;
  579. }
  580. nStressServerLimit++;
  581. #endif
  582. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  583. if( pServer->GetTreeItemFromFav( ) != NULL )
  584. {
  585. // format is domain/server
  586. if( pServer->GetDomain( ) )
  587. {
  588. dwByteCount += ( wcslen( pServer->GetDomain( )->GetName() ) * 2 );
  589. dwByteCount += 2;
  590. }
  591. dwByteCount += ( wcslen( pServer->GetName() ) + 1) * 2;
  592. }
  593. }
  594. LPWSTR pBuffer = NULL;
  595. if( dwByteCount != 0 )
  596. {
  597. dwByteCount += 2; // for ending null
  598. // Allocate memory.
  599. if( ( pBuffer = ( LPWSTR )LocalAlloc( LPTR, dwByteCount ) ) != NULL )
  600. {
  601. // Traverse list again and copy servers to buffer.
  602. LPWSTR pTemp = pBuffer;
  603. pos = m_ServerList.GetHeadPosition();
  604. #ifdef _STRESS_BUILD
  605. nStressServerLimit = 0;
  606. #endif
  607. while(pos)
  608. {
  609. #ifdef _STRESS_BUILD
  610. if( nStressServerLimit >= 10000 )
  611. {
  612. break;
  613. }
  614. nStressServerLimit++;
  615. #endif
  616. // Go to the next server in the list
  617. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  618. if( pServer->GetTreeItemFromFav( ) != NULL )
  619. {
  620. if( pServer->GetDomain( ) )
  621. {
  622. lstrcpy( pTemp , pServer->GetDomain( )->GetName( ) );
  623. lstrcat( pTemp , L"/" );
  624. }
  625. lstrcat(pTemp, pServer->GetName());
  626. pTemp += ( wcslen( pTemp ) + 1);
  627. }
  628. }
  629. *pTemp = L'\0'; // ending null
  630. RegSetValueEx (hKeyWinAdmin, szFavList, 0, REG_MULTI_SZ, (PBYTE)pBuffer, dwByteCount);
  631. LocalFree(pBuffer);
  632. }
  633. }
  634. else
  635. {
  636. RegDeleteValue( hKeyWinAdmin , szFavList );
  637. }
  638. UnlockServerList();
  639. // Write the persistent connections preference
  640. dwValue = m_ConnectionsPersistent;
  641. RegSetValueEx( hKeyWinAdmin,
  642. szConnectionsPersistent,
  643. 0,
  644. REG_DWORD,
  645. (LPBYTE)&dwValue,
  646. sizeof(DWORD)
  647. );
  648. if( m_ConnectionsPersistent )
  649. {
  650. // Create a multistring of the persistent connections
  651. // loop through the list of servers and see how much memory
  652. // to allocate for the multistring.
  653. dwByteCount = 0;
  654. LockServerList();
  655. pos = m_ServerList.GetHeadPosition();
  656. while(pos)
  657. {
  658. // Go to the next server in the list
  659. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  660. if( pServer->IsState(SS_GOOD) )
  661. {
  662. dwByteCount += (wcslen(pServer->GetName()) + 1) * 2;
  663. }
  664. }
  665. UnlockServerList();
  666. dwByteCount += 2; // for ending null
  667. // Allocate memory.
  668. pBuffer = NULL;
  669. if( ( pBuffer = ( LPWSTR )LocalAlloc( LPTR, dwByteCount ) ) != NULL )
  670. {
  671. // Traverse list again and copy servers to buffer.
  672. LPWSTR pTemp = pBuffer;
  673. LockServerList();
  674. pos = m_ServerList.GetHeadPosition();
  675. while(pos)
  676. {
  677. // Go to the next server in the list
  678. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  679. if( pServer->IsState(SS_GOOD) )
  680. {
  681. wcscpy(pTemp, pServer->GetName());
  682. pTemp += (wcslen(pServer->GetName()) + 1);
  683. }
  684. }
  685. UnlockServerList();
  686. *pTemp = L'\0'; // ending null
  687. // write the registry entry
  688. RegSetValueEx(hKeyWinAdmin, szConnections, 0, REG_MULTI_SZ, (PBYTE)pBuffer, dwByteCount);
  689. LocalFree(pBuffer);
  690. }
  691. }
  692. else
  693. {
  694. RegDeleteValue(hKeyWinAdmin, szConnections);
  695. }
  696. // persist treeview state
  697. // send message to treeview to retreive tv state bits
  698. CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
  699. CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
  700. DWORD dwTVStates = 0;
  701. if( p != NULL )
  702. {
  703. dwTVStates = ( DWORD )p->SendMessage( WM_ADMIN_GET_TV_STATES , 0 , 0 );
  704. }
  705. RegSetValueEx( hKeyWinAdmin , szTVStates , 0 , REG_DWORD , ( PBYTE )&dwTVStates , sizeof( DWORD ) );
  706. RegCloseKey(hKeyWinAdmin);
  707. } // end CWinAdminDoc::WritePreferences
  708. /*
  709. static TCHAR DOMAIN_KEY[] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon");
  710. static TCHAR PRIMARY_VAL[] = TEXT("CachePrimaryDomain");
  711. static TCHAR CACHE_VAL[] = TEXT("DomainCache");
  712. */
  713. /////////////////////////////////////////////////////////////////////////////
  714. // CWinAdminDoc::BuildDomainList
  715. //
  716. // Read the list of trusted domains from the registry
  717. // and build a linked list of CDomains
  718. //
  719. void CWinAdminDoc::BuildDomainList()
  720. {
  721. /*
  722. HKEY hKey,hSubKey;
  723. DWORD size = 128;
  724. DWORD dwIndex = 0;
  725. */
  726. PDOMAIN_CONTROLLER_INFO pDCI;
  727. if( DsGetDcName( NULL ,
  728. NULL ,
  729. NULL ,
  730. NULL ,
  731. DS_RETURN_FLAT_NAME,
  732. &pDCI ) == NO_ERROR )
  733. {
  734. CDomain *pDomain = new CDomain( pDCI->DomainName );
  735. if(pDomain != NULL )
  736. {
  737. pDomain->SetCurrentDomain();
  738. m_pCurrentDomain = pDomain;
  739. AddDomain( pDomain );
  740. }
  741. NetApiBufferFree( pDCI );
  742. // query for the other domains
  743. LPWSTR szDomainNames = NULL;
  744. if( NetEnumerateTrustedDomains( NULL ,
  745. &szDomainNames ) == ERROR_SUCCESS )
  746. {
  747. LPWSTR pszDN = szDomainNames;
  748. while( *pszDN )
  749. {
  750. CDomain *pNewDomain = new CDomain( pszDN );
  751. if( pNewDomain != NULL )
  752. {
  753. AddDomain( pNewDomain );
  754. }
  755. pszDN += ( wcslen( pszDN ) + 1 );
  756. }
  757. NetApiBufferFree( szDomainNames );
  758. }
  759. }
  760. } // end CWinAdminDoc::BuildDomainList
  761. /////////////////////////////////////////////////////////////////////////////
  762. // CWinAdminDoc::AddDomain
  763. //
  764. // Add a Domain to DomainList in sorted order
  765. //
  766. void CWinAdminDoc::AddDomain(CDomain *pNewDomain)
  767. {
  768. ASSERT(pNewDomain);
  769. BOOLEAN bAdded = FALSE;
  770. POSITION pos, oldpos;
  771. int Index;
  772. // Traverse the DomainList and insert this new Domain,
  773. // keeping the list sorted by Name.
  774. for(Index = 0, pos = m_DomainList.GetHeadPosition(); pos != NULL; Index++) {
  775. oldpos = pos;
  776. CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
  777. if(wcscmp(pDomain->GetName(), pNewDomain->GetName()) > 0) {
  778. // The new object belongs before the current list object.
  779. m_DomainList.InsertBefore(oldpos, pNewDomain);
  780. bAdded = TRUE;
  781. // NOTE: If you add a critical section to protect the domain list,
  782. // you should change this to a break; and unlock the list
  783. // just before exiting this function
  784. return;
  785. }
  786. }
  787. // If we haven't yet added the Domain, add it now to the tail
  788. // of the list.
  789. if(!bAdded) {
  790. m_DomainList.AddTail(pNewDomain);
  791. }
  792. } // end CWinAdminDoc::AddDomain
  793. /////////////////////////////////////////////////////////////////////////////
  794. // CWinAdminDoc::BuildWdList
  795. //
  796. // Read the list of Wds from the registry
  797. // and build a linked list of CWds
  798. //
  799. void CWinAdminDoc::BuildWdList()
  800. {
  801. LONG Status;
  802. ULONG Index, ByteCount, Entries;
  803. WDNAME WdKey;
  804. LONG QStatus;
  805. WDCONFIG2 WdConfig;
  806. TCHAR WdDll[MAX_PATH];
  807. CWd *pWd;
  808. // Initialize the Wd list.
  809. for ( Index = 0, Entries = 1, ByteCount = sizeof(WDNAME);
  810. (Status =
  811. RegWdEnumerate( SERVERNAME_CURRENT,
  812. &Index,
  813. &Entries,
  814. WdKey,
  815. &ByteCount )) == ERROR_SUCCESS;
  816. ByteCount = sizeof(WDNAME) ) {
  817. if ( ( QStatus = RegWdQuery( SERVERNAME_CURRENT, WdKey, &WdConfig,
  818. sizeof(WdConfig),
  819. &ByteCount ) ) != ERROR_SUCCESS ) {
  820. //If this is added back in, the signature of StandardErrorMessage has changed!!!!
  821. #if 0
  822. STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, QStatus,
  823. IDP_ERROR_REGWDQUERY, WdKey ))
  824. return(FALSE);
  825. #endif
  826. }
  827. /*
  828. * Only place this Wd in the WdList if it's DLL is present
  829. * on the system.
  830. */
  831. GetSystemDirectory( WdDll, MAX_PATH );
  832. lstrcat( WdDll, TEXT("\\Drivers\\") );
  833. lstrcat( WdDll, WdConfig.Wd.WdDLL );
  834. lstrcat( WdDll, TEXT(".sys" ) );
  835. if ( _waccess( WdDll, 0 ) != 0 )
  836. continue;
  837. pWd = new CWd(&WdConfig, (PWDNAME)&WdKey);
  838. m_WdList.AddTail(pWd);
  839. }
  840. } // end CWinAdminDoc::BuildWdList
  841. /////////////////////////////////////////////////////////////////////////////
  842. // CWinAdminDoc::Refresh
  843. //
  844. // Perform a Refresh
  845. //
  846. void CWinAdminDoc::Refresh()
  847. {
  848. // We don't want to refresh if we are currently doing one
  849. if(m_InRefresh) return;
  850. CWaitCursor Nikki;
  851. m_InRefresh = TRUE;
  852. // Wake up our background tasks that enumerates servers
  853. POSITION pos = m_DomainList.GetHeadPosition();
  854. while(pos) {
  855. CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
  856. pDomain->SetEnumEvent();
  857. }
  858. // Make each of the Server's background tasks enumerate WinStations
  859. LockServerList();
  860. pos = m_ServerList.GetHeadPosition();
  861. while(pos) {
  862. ULONG WSEventFlags;
  863. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  864. if(pServer->IsHandleGood() && pServer->IsState(SS_GOOD)) {
  865. WinStationWaitSystemEvent(pServer->GetHandle(), WEVENT_FLUSH, &WSEventFlags);
  866. }
  867. }
  868. UnlockServerList();
  869. // If the current page is a processes page, tell appropriate process enumeration
  870. // background thread to do their thing
  871. if(m_CurrentView == VIEW_ALL_SERVERS && m_CurrentPage == PAGE_AS_PROCESSES) {
  872. UpdateAllProcesses();
  873. }
  874. if(m_CurrentView == VIEW_DOMAIN && m_CurrentPage == PAGE_DOMAIN_PROCESSES) {
  875. UpdateAllProcesses();
  876. }
  877. if((m_CurrentView == VIEW_SERVER && m_CurrentPage == PAGE_PROCESSES)
  878. || (m_CurrentView == VIEW_WINSTATION && m_CurrentPage == PAGE_WS_PROCESSES)) {
  879. m_ProcessWakeUpEvent.SetEvent();
  880. }
  881. m_InRefresh = FALSE;
  882. } // end CWinAdminDoc::Refresh
  883. /////////////////////////////////////////////////////////////////////////////
  884. // CWinAdminDoc::AddServer
  885. //
  886. // Add a Server to ServerList in sorted order
  887. //
  888. void CWinAdminDoc::AddServer(CServer *pNewServer)
  889. {
  890. ASSERT(pNewServer);
  891. LockServerList();
  892. BOOLEAN bAdded = FALSE;
  893. POSITION pos, oldpos;
  894. int Index;
  895. // Traverse the ServerList and insert this new Server,
  896. // keeping the list sorted by Name.
  897. for(Index = 0, pos = m_ServerList.GetHeadPosition(); pos != NULL; Index++)
  898. {
  899. oldpos = pos;
  900. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  901. if( lstrcmpi( pServer->GetName() , pNewServer->GetName() ) > 0 )
  902. {
  903. // The new object belongs before the current list object.
  904. m_ServerList.InsertBefore(oldpos, pNewServer);
  905. bAdded = TRUE;
  906. break;
  907. }
  908. }
  909. // If we haven't yet added the Server, add it now to the tail
  910. // of the list.
  911. if(!bAdded)
  912. {
  913. m_ServerList.AddTail(pNewServer);
  914. }
  915. UnlockServerList();
  916. } // end CWinAdminDoc::AddServer
  917. //=----------------------------------------------------------------------------------
  918. //= AddToFavoritesNow will add all persisted servers to the fav node and
  919. //= connect to them as appropriate.
  920. void CWinAdminDoc::AddToFavoritesNow( )
  921. {
  922. CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
  923. CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
  924. LPTSTR pszDomain = NULL;
  925. LPTSTR pszServer = NULL;
  926. LPTSTR pszDomServer = NULL;
  927. int nJump = 0;
  928. POSITION pos;
  929. if( m_pszFavList != NULL )
  930. {
  931. pszDomServer = m_pszFavList;
  932. while( *pszDomServer )
  933. {
  934. pos = m_DomainList.GetHeadPosition();
  935. nJump = wcslen( pszDomServer );
  936. pszDomain = pszDomServer;
  937. TCHAR *pTemp = pszDomServer;
  938. while( *pTemp )
  939. {
  940. if( *pTemp == L'/' )
  941. {
  942. break;
  943. }
  944. pTemp++;
  945. }
  946. if(*pTemp == L'/')
  947. {
  948. *pTemp = 0;
  949. pTemp++;
  950. pszServer = pTemp;
  951. }
  952. else
  953. {
  954. //there is no domain for this server
  955. pszServer = pszDomServer;
  956. pszDomain = NULL;
  957. }
  958. // let's check to see if server already exist primarily "this computer"
  959. if( m_pCurrentServer != NULL && lstrcmpi( pszServer , m_pCurrentServer->GetName( ) ) == 0 )
  960. {
  961. p->SendMessage(WM_ADMIN_ADDSERVERTOFAV , 0 , (LPARAM)m_pCurrentServer );
  962. }
  963. else
  964. {
  965. CDomain *pDomain = NULL;
  966. CServer *pServer = NULL;
  967. if( pszDomain )
  968. {
  969. BOOL bFound = FALSE;
  970. while( pos )
  971. {
  972. pDomain = (CDomain*)m_DomainList.GetNext(pos);
  973. if( _wcsicmp( pDomain->GetName() , pszDomain ) == 0 )
  974. {
  975. bFound = TRUE;
  976. break;
  977. }
  978. }
  979. if(!bFound)
  980. {
  981. pDomain = new CDomain( pszDomain );
  982. if( pDomain != NULL )
  983. {
  984. AddDomain( pDomain );
  985. p->SendMessage( WM_ADMIN_ADD_DOMAIN , (WPARAM)NULL , ( LPARAM )pDomain );
  986. }
  987. }
  988. }
  989. pServer = new CServer( pDomain , pszServer , FALSE , FALSE );
  990. if( pServer != NULL )
  991. {
  992. pServer->SetManualFind( );
  993. AddServer(pServer);
  994. p->SendMessage(WM_ADMIN_ADDSERVERTOFAV , 0 , (LPARAM)pServer);
  995. }
  996. }
  997. pszDomServer += nJump + 1;
  998. }
  999. }
  1000. // check to see if we need to connect these servers.
  1001. LockServerList();
  1002. pos = m_ServerList.GetHeadPosition();
  1003. while( pos )
  1004. {
  1005. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  1006. if( ShouldConnect( pServer->GetName( ) ) )
  1007. {
  1008. if( pServer->GetTreeItemFromFav( ) != NULL )
  1009. {
  1010. pServer->Connect( );
  1011. }
  1012. }
  1013. }
  1014. UnlockServerList();
  1015. }
  1016. /////////////////////////////////////////////////////////////////////////////
  1017. // CWinAdminDoc::FindServerByName
  1018. //
  1019. // returns a pointer to a given CServer object if it is in our list
  1020. //
  1021. CServer* CWinAdminDoc::FindServerByName(TCHAR *pServerName)
  1022. {
  1023. ASSERT(pServerName);
  1024. LockServerList();
  1025. POSITION pos = m_ServerList.GetHeadPosition();
  1026. while(pos) {
  1027. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  1028. if( lstrcmpi( pServer->GetName() , pServerName ) == 0)
  1029. {
  1030. UnlockServerList();
  1031. return pServer;
  1032. }
  1033. }
  1034. UnlockServerList();
  1035. return NULL;
  1036. } // end CWinAdminDoc::FindServerByName
  1037. /////////////////////////////////////////////////////////////////////////////
  1038. // CWinAdminDoc::FindWdByName
  1039. //
  1040. // returns a pointer to a given CWd object if it is in our list
  1041. //
  1042. CWd* CWinAdminDoc::FindWdByName(TCHAR *pWdName)
  1043. {
  1044. ASSERT(pWdName);
  1045. LockWdList();
  1046. POSITION pos = m_WdList.GetHeadPosition();
  1047. while(pos) {
  1048. CWd *pWd = (CWd*)m_WdList.GetNext(pos);
  1049. if(wcscmp(pWd->GetName(), pWdName) == 0) {
  1050. UnlockWdList();
  1051. return pWd;
  1052. }
  1053. }
  1054. UnlockWdList();
  1055. return NULL;
  1056. } // end CWinAdminDoc::FindWdByName
  1057. /////////////////////////////////////////////////////////////////////////////
  1058. // CWinAdminDoc::SetTreeCurrent
  1059. //
  1060. void CWinAdminDoc::SetTreeCurrent(CObject* selected, NODETYPE type)
  1061. {
  1062. m_CurrentSelectedNode = selected;
  1063. m_CurrentSelectedType = type;
  1064. // We need to be able to check the current selected type from other
  1065. // threads, in particular when resetting, disconnecting and sending
  1066. // a message, to check that we still have a valid winstation
  1067. CWinAdminDoc::gm_CurrentSelType = type;
  1068. CString TitleString;
  1069. // Set the window title
  1070. switch(m_CurrentSelectedType) {
  1071. case NODE_ALL_SERVERS:
  1072. TitleString.LoadString(IDS_TREEROOT);
  1073. SetTitle(TitleString);
  1074. break;
  1075. case NODE_DOMAIN:
  1076. TitleString.Format(TEXT("\\\\%s"), ((CDomain*)selected)->GetName());
  1077. SetTitle(TitleString);
  1078. break;
  1079. case NODE_SERVER:
  1080. SetTitle(((CServer*)selected)->GetName());
  1081. break;
  1082. case NODE_WINSTATION:
  1083. SetTitle(((CWinStation*)selected)->GetServer()->GetName());
  1084. break;
  1085. case NODE_THIS_COMP:
  1086. TitleString.LoadString( IDS_THISCOMPUTER );
  1087. SetTitle( TitleString );
  1088. break;
  1089. case NODE_FAV_LIST:
  1090. TitleString.LoadString( IDS_FAVSERVERS );
  1091. SetTitle( TitleString );
  1092. break;
  1093. }
  1094. } // end CWinAdminDoc::SetTreeCurrent
  1095. /////////////////////////////////////////////////////////////////////////////
  1096. // CWinAdminDoc::SendWinStationMessage
  1097. //
  1098. // bTemp is TRUE if message is to be sent to the temporarily selected
  1099. // tree item.
  1100. //
  1101. void CWinAdminDoc::SendWinStationMessage(BOOL bTemp, MessageParms *pParms)
  1102. {
  1103. ASSERT(pParms);
  1104. // Are we sending a message to temporarily selected tree item?
  1105. if(bTemp)
  1106. {
  1107. // Is the temporarily selected item in the tree a WinStation?
  1108. if(m_TempSelectedType == NODE_WINSTATION)
  1109. {
  1110. // If the winstation we're working on disappears before we get here
  1111. // then just return
  1112. if (m_CurrentSelectedType != NODE_WINSTATION)
  1113. {
  1114. return;
  1115. }
  1116. pParms->pWinStation = (CWinStation*)m_pTempSelectedNode;
  1117. pParms->bActionOnCurrentSelection = TRUE;
  1118. AfxBeginThread((AFX_THREADPROC)CWinStation::SendMessage, pParms);
  1119. }
  1120. return;
  1121. }
  1122. // Is the WinStation selected in the tree?
  1123. if(m_CurrentSelectedType == NODE_WINSTATION)
  1124. {
  1125. pParms->pWinStation = (CWinStation*)m_CurrentSelectedNode;
  1126. pParms->bActionOnCurrentSelection = TRUE;
  1127. AfxBeginThread((AFX_THREADPROC)CWinStation::SendMessage, pParms);
  1128. }
  1129. // Go through the list of WinStations on the currently selected server
  1130. // and send messages to those that are selected
  1131. else if(m_CurrentView == VIEW_SERVER)
  1132. {
  1133. // Get a pointer to the selected server
  1134. CServer *pServer = (CServer*)m_CurrentSelectedNode;
  1135. // Lock the server's list of WinStations
  1136. pServer->LockWinStationList();
  1137. // Get a pointer to the server's list of WinStations
  1138. CObList *pWinStationList = pServer->GetWinStationList();
  1139. // Iterate through the WinStation list
  1140. POSITION pos = pWinStationList->GetHeadPosition();
  1141. while(pos)
  1142. {
  1143. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1144. if(pWinStation->IsSelected())
  1145. {
  1146. // Make a copy of the MessageParms
  1147. MessageParms *pParmsCopy = new MessageParms;
  1148. if(pParmsCopy)
  1149. {
  1150. memcpy(pParmsCopy, pParms, sizeof(MessageParms));
  1151. // Start a thread to send the message
  1152. pParmsCopy->pWinStation = pWinStation;
  1153. pParmsCopy->bActionOnCurrentSelection = FALSE;
  1154. AfxBeginThread((AFX_THREADPROC)CWinStation::SendMessage, pParmsCopy);
  1155. }
  1156. }
  1157. }
  1158. // Unlock the list of WinStations
  1159. pServer->UnlockWinStationList();
  1160. // Delete MessageParms - we sent copies to the WinStation objects
  1161. // They will delete their copies
  1162. delete pParms;
  1163. }
  1164. else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN)
  1165. {
  1166. LockServerList();
  1167. POSITION pos2 = m_ServerList.GetHeadPosition();
  1168. while(pos2)
  1169. {
  1170. // Get a pointer to the server
  1171. CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
  1172. // Lock the server's list of WinStations
  1173. pServer->LockWinStationList();
  1174. // Get a pointer to the server's list of WinStations
  1175. CObList *pWinStationList = pServer->GetWinStationList();
  1176. // Iterate through the WinStation list
  1177. POSITION pos = pWinStationList->GetHeadPosition();
  1178. while(pos)
  1179. {
  1180. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1181. if(pWinStation->IsSelected())
  1182. {
  1183. // Make a copy of the MessageParms
  1184. MessageParms *pParmsCopy = new MessageParms;
  1185. if(pParmsCopy)
  1186. {
  1187. memcpy(pParmsCopy, pParms, sizeof(MessageParms));
  1188. // Start a thread to send the message
  1189. pParmsCopy->pWinStation = pWinStation;
  1190. pParmsCopy->bActionOnCurrentSelection = FALSE;
  1191. AfxBeginThread((AFX_THREADPROC)CWinStation::SendMessage, pParmsCopy);
  1192. }
  1193. }
  1194. }
  1195. // Unlock the list of WinStations
  1196. pServer->UnlockWinStationList();
  1197. }
  1198. UnlockServerList();
  1199. // Delete MessageParms - we sent copies to the WinStation objects
  1200. // They will delete their copies
  1201. delete pParms;
  1202. }
  1203. } // end CWinAdminDoc::SendWinStationMessage
  1204. /////////////////////////////////////////////////////////////////////////////
  1205. // CWinAdminDoc::ConnectWinStation
  1206. //
  1207. // bTemp is TRUE if we are to connect to the temporarily selected tree item.
  1208. //
  1209. void CWinAdminDoc::ConnectWinStation(BOOL bTemp, BOOL bUser)
  1210. {
  1211. // Are we connecting to temporarily selected tree item?
  1212. if(bTemp) {
  1213. // Is the temporarily selected item in the tree a WinStation?
  1214. if(m_TempSelectedType == NODE_WINSTATION) {
  1215. ((CWinStation*)m_pTempSelectedNode)->Connect(NULL);
  1216. }
  1217. return;
  1218. }
  1219. if(m_CurrentSelectedType == NODE_WINSTATION) {
  1220. ((CWinStation*)m_CurrentSelectedNode)->Connect(NULL);
  1221. }
  1222. // Go through the list of WinStations on the currently selected server
  1223. // and disconnect those that are selected
  1224. else if(m_CurrentView == VIEW_SERVER) {
  1225. // Get a pointer to the selected server
  1226. CServer *pServer = (CServer*)m_CurrentSelectedNode;
  1227. // Lock the server's list of WinStations
  1228. pServer->LockWinStationList();
  1229. // Get a pointer to the server's list of WinStations
  1230. CObList *pWinStationList = pServer->GetWinStationList();
  1231. // Iterate through the WinStation list
  1232. POSITION pos = pWinStationList->GetHeadPosition();
  1233. while(pos) {
  1234. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1235. if(pWinStation->IsSelected()) {
  1236. // do the connect
  1237. pWinStation->Connect(bUser);
  1238. break; // we can only connect to one WinStation
  1239. }
  1240. }
  1241. // Unlock the list of WinStations
  1242. pServer->UnlockWinStationList();
  1243. }
  1244. else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
  1245. LockServerList();
  1246. POSITION pos2 = m_ServerList.GetHeadPosition();
  1247. while(pos2) {
  1248. // Get a pointer to the server
  1249. CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
  1250. // Lock the server's list of WinStations
  1251. pServer->LockWinStationList();
  1252. // Get a pointer to the server's list of WinStations
  1253. CObList *pWinStationList = pServer->GetWinStationList();
  1254. // Iterate through the WinStation list
  1255. POSITION pos = pWinStationList->GetHeadPosition();
  1256. while(pos) {
  1257. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1258. if(pWinStation->IsSelected()) {
  1259. // do the connect
  1260. pWinStation->Connect(bUser);
  1261. break; // we can only connect to one WinStation
  1262. }
  1263. }
  1264. // Unlock the list of WinStations
  1265. pServer->UnlockWinStationList();
  1266. }
  1267. UnlockServerList();
  1268. }
  1269. } // end CWinAdminDoc::ConnectWinStation
  1270. /////////////////////////////////////////////////////////////////////////////
  1271. // CWinAdminDoc::StatusWinStation
  1272. //
  1273. // bTemp is TRUE if we are to show status for the temporarily selected tree item.
  1274. //
  1275. void CWinAdminDoc::StatusWinStation(BOOL bTemp)
  1276. {
  1277. // Are we showing status for the temporarily selected tree item?
  1278. if(bTemp) {
  1279. // Is the temporarily selected item in the tree a WinStation?
  1280. if(m_TempSelectedType == NODE_WINSTATION) {
  1281. ((CWinStation*)m_pTempSelectedNode)->ShowStatus();
  1282. }
  1283. return;
  1284. }
  1285. if(m_CurrentSelectedType == NODE_WINSTATION) {
  1286. ((CWinStation*)m_CurrentSelectedNode)->ShowStatus();
  1287. }
  1288. // Go through the list of WinStations on the currently selected server
  1289. // and show status for those that are selected
  1290. else if(m_CurrentView == VIEW_SERVER) {
  1291. // Get a pointer to the selected server
  1292. CServer *pServer = (CServer*)m_CurrentSelectedNode;
  1293. // Lock the server's list of WinStations
  1294. pServer->LockWinStationList();
  1295. // Get a pointer to the server's list of WinStations
  1296. CObList *pWinStationList = pServer->GetWinStationList();
  1297. // Iterate through the WinStation list
  1298. POSITION pos = pWinStationList->GetHeadPosition();
  1299. while(pos) {
  1300. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1301. if(pWinStation->IsSelected()) {
  1302. pWinStation->ShowStatus();
  1303. }
  1304. }
  1305. // Unlock the list of WinStations
  1306. pServer->UnlockWinStationList();
  1307. }
  1308. else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
  1309. LockServerList();
  1310. POSITION pos2 = m_ServerList.GetHeadPosition();
  1311. while(pos2) {
  1312. // Get a pointer to the server
  1313. CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
  1314. // Lock the server's list of WinStations
  1315. pServer->LockWinStationList();
  1316. // Get a pointer to the server's list of WinStations
  1317. CObList *pWinStationList = pServer->GetWinStationList();
  1318. // Iterate through the WinStation list
  1319. POSITION pos = pWinStationList->GetHeadPosition();
  1320. while(pos) {
  1321. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1322. if(pWinStation->IsSelected()) {
  1323. pWinStation->ShowStatus();
  1324. }
  1325. }
  1326. // Unlock the list of WinStations
  1327. pServer->UnlockWinStationList();
  1328. }
  1329. UnlockServerList();
  1330. }
  1331. } // end CWinAdminDoc::StatusWinStation
  1332. /////////////////////////////////////////////////////////////////////////////
  1333. // CWinAdminDoc::DisconnectWinStation
  1334. //
  1335. // bTemp is TRUE if we are disconnecting the temporarily selected tree item.
  1336. //
  1337. void CWinAdminDoc::DisconnectWinStation(BOOL bTemp)
  1338. {
  1339. CWinStation * pCurWinStation;
  1340. CServer * pCurServer;
  1341. // Are we disconnecting the temporarily selected tree item?
  1342. if(bTemp)
  1343. {
  1344. // Is the temporarily selected item in the tree a WinStation?
  1345. if(m_TempSelectedType == NODE_WINSTATION)
  1346. {
  1347. // If the winstation we're working on disappears before we get here
  1348. // then just return
  1349. if (m_CurrentSelectedType != NODE_WINSTATION)
  1350. {
  1351. return;
  1352. }
  1353. // create a disconnect parameters structure
  1354. DisconnectParms * pDisconParms = new DisconnectParms;
  1355. if(pDisconParms)
  1356. {
  1357. // get currecnt selected node winstation and server
  1358. pCurWinStation = (CWinStation*)m_pTempSelectedNode;
  1359. pCurServer = pCurWinStation->GetServer();
  1360. pDisconParms->hServer = pCurServer->GetHandle();
  1361. pDisconParms->ulLogonId = pCurWinStation->GetLogonId();
  1362. pDisconParms->bActionOnCurrentSelection = TRUE;
  1363. AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, pDisconParms);
  1364. // the thread will delete pDisconParms
  1365. }
  1366. }
  1367. return;
  1368. }
  1369. if(m_CurrentSelectedType == NODE_WINSTATION)
  1370. {
  1371. // create a disconnect parameters structure
  1372. DisconnectParms *pDisconParms = new DisconnectParms;
  1373. if(pDisconParms)
  1374. {
  1375. // get currecnt selected node winstation and server
  1376. pCurWinStation = (CWinStation*)m_CurrentSelectedNode;
  1377. pCurServer = pCurWinStation->GetServer();
  1378. pDisconParms->hServer = pCurServer->GetHandle();
  1379. pDisconParms->ulLogonId = pCurWinStation->GetLogonId();
  1380. pDisconParms->bActionOnCurrentSelection = TRUE;
  1381. AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, pDisconParms);
  1382. // the thread will delete pDisconParms
  1383. }
  1384. }
  1385. // Go through the list of WinStations on the currently selected server
  1386. // and disconnect those that are selected
  1387. else if(m_CurrentView == VIEW_SERVER)
  1388. {
  1389. // Get a pointer to the selected server
  1390. CServer *pServer = (CServer*)m_CurrentSelectedNode;
  1391. // Lock the server's list of WinStations
  1392. pServer->LockWinStationList();
  1393. // Get a pointer to the server's list of WinStations
  1394. CObList *pWinStationList = pServer->GetWinStationList();
  1395. // Iterate through the WinStation list
  1396. POSITION pos = pWinStationList->GetHeadPosition();
  1397. while(pos)
  1398. {
  1399. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1400. if(pWinStation->IsSelected())
  1401. {
  1402. // create a disconnect parameters structure
  1403. DisconnectParms *pDisconParms = new DisconnectParms;
  1404. if(pDisconParms)
  1405. {
  1406. // get currecnt selected node winstation and server
  1407. //pCurWinStation = (CWinStation*)m_pTempSelectedNode;
  1408. pCurServer = pWinStation->GetServer();
  1409. pDisconParms->hServer = pCurServer->GetHandle();
  1410. pDisconParms->ulLogonId = pWinStation->GetLogonId();
  1411. pDisconParms->bActionOnCurrentSelection = FALSE;
  1412. // Start a thread to do the disconnect
  1413. AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, pDisconParms);
  1414. // the thread will delete pDisconParms
  1415. }
  1416. }
  1417. }
  1418. // Unlock the list of WinStations
  1419. pServer->UnlockWinStationList();
  1420. }
  1421. else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN)
  1422. {
  1423. LockServerList();
  1424. POSITION pos2 = m_ServerList.GetHeadPosition();
  1425. while(pos2)
  1426. {
  1427. // Get a pointer to the server
  1428. CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
  1429. // Lock the server's list of WinStations
  1430. pServer->LockWinStationList();
  1431. // Get a pointer to the server's list of WinStations
  1432. CObList *pWinStationList = pServer->GetWinStationList();
  1433. // Iterate through the WinStation list
  1434. POSITION pos = pWinStationList->GetHeadPosition();
  1435. while(pos)
  1436. {
  1437. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1438. if(pWinStation->IsSelected())
  1439. {
  1440. // create a disconnect parameters structure
  1441. DisconnectParms *pDisconParms = new DisconnectParms;
  1442. if(pDisconParms)
  1443. {
  1444. // get currecnt selected node winstation and server
  1445. //pCurWinStation = (CWinStation*)m_pTempSelectedNode;
  1446. pCurServer = pWinStation->GetServer();
  1447. pDisconParms->hServer = pCurServer->GetHandle();
  1448. pDisconParms->ulLogonId = pWinStation->GetLogonId();
  1449. pDisconParms->bActionOnCurrentSelection = FALSE;
  1450. // Start a thread to do the disconnect
  1451. AfxBeginThread((AFX_THREADPROC)CWinStation::Disconnect, pDisconParms);
  1452. // the thread will delete pDisconParms
  1453. }
  1454. }
  1455. }
  1456. // Unlock the list of WinStations
  1457. pServer->UnlockWinStationList();
  1458. }
  1459. UnlockServerList();
  1460. }
  1461. } // end CWinAdminDoc::DisconnectWinStation
  1462. /////////////////////////////////////////////////////////////////////////////
  1463. // CWinAdminDoc::ResetWinStation
  1464. //
  1465. // bTemp is TRUE if we are to reset the temporarily selected tree item.
  1466. // bReset is TRUE if reset, FALSE if logoff
  1467. //
  1468. void CWinAdminDoc::ResetWinStation(BOOL bTemp, BOOL bReset)
  1469. {
  1470. // Are we resetting the temporarily selected tree item?
  1471. if(bTemp)
  1472. {
  1473. // Is the temporarily selected item in the tree a WinStation?
  1474. if(m_TempSelectedType == NODE_WINSTATION)
  1475. {
  1476. // If the winstation we're working on disappears before we get here
  1477. // then just return
  1478. if (m_CurrentSelectedType != NODE_WINSTATION)
  1479. {
  1480. return;
  1481. }
  1482. // create a reset parameters structure
  1483. ResetParms *pResetParms = new ResetParms;
  1484. if(pResetParms)
  1485. {
  1486. pResetParms->pWinStation = (CWinStation*)m_pTempSelectedNode;
  1487. pResetParms->bReset = bReset;
  1488. pResetParms->bActionOnCurrentSelection = TRUE;
  1489. AfxBeginThread((AFX_THREADPROC)CWinStation::Reset, pResetParms);
  1490. // the thread will delete pResetParms
  1491. }
  1492. }
  1493. return;
  1494. }
  1495. if(m_CurrentSelectedType == NODE_WINSTATION)
  1496. {
  1497. // create a reset parameters structure
  1498. ResetParms *pResetParms = new ResetParms;
  1499. if(pResetParms)
  1500. {
  1501. pResetParms->pWinStation = (CWinStation*)m_CurrentSelectedNode;
  1502. pResetParms->bReset = bReset;
  1503. pResetParms->bActionOnCurrentSelection = TRUE;
  1504. AfxBeginThread((AFX_THREADPROC)CWinStation::Reset, pResetParms);
  1505. // the thread will delete pResetParms
  1506. }
  1507. }
  1508. // Go through the list of WinStations on the currently selected server
  1509. // and reset those that are selected
  1510. else if(m_CurrentView == VIEW_SERVER)
  1511. {
  1512. // Get a pointer to the selected server
  1513. CServer *pServer = (CServer*)m_CurrentSelectedNode;
  1514. // Lock the server's list of WinStations
  1515. pServer->LockWinStationList();
  1516. // Get a pointer to the server's list of WinStations
  1517. CObList *pWinStationList = pServer->GetWinStationList();
  1518. // Iterate through the WinStation list
  1519. POSITION pos = pWinStationList->GetHeadPosition();
  1520. while(pos)
  1521. {
  1522. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1523. if(pWinStation->IsSelected())
  1524. {
  1525. // create a reset parameters structure
  1526. ResetParms *pResetParms = new ResetParms;
  1527. if(pResetParms)
  1528. {
  1529. pResetParms->pWinStation = pWinStation;
  1530. pResetParms->bReset = bReset;
  1531. pResetParms->bActionOnCurrentSelection = FALSE;
  1532. // Start a thread to do the reset
  1533. AfxBeginThread((AFX_THREADPROC)CWinStation::Reset, pResetParms);
  1534. // the thread will delete pResetParms
  1535. }
  1536. }
  1537. }
  1538. // Unlock the list of WinStations
  1539. pServer->UnlockWinStationList();
  1540. }
  1541. else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN)
  1542. {
  1543. LockServerList();
  1544. POSITION pos2 = m_ServerList.GetHeadPosition();
  1545. while(pos2)
  1546. {
  1547. // Get a pointer to the server
  1548. CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
  1549. // Lock the server's list of WinStations
  1550. pServer->LockWinStationList();
  1551. // Get a pointer to the server's list of WinStations
  1552. CObList *pWinStationList = pServer->GetWinStationList();
  1553. // Iterate through the WinStation list
  1554. POSITION pos = pWinStationList->GetHeadPosition();
  1555. while(pos)
  1556. {
  1557. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1558. if( pWinStationList != NULL && pWinStation->IsSelected() )
  1559. {
  1560. if( GetCurrentPage( ) == PAGE_AS_USERS && pWinStation->GetState() == State_Listen )
  1561. {
  1562. // from a user experience if the listener winstation has been selected from a
  1563. // previous page that went out of focus - then not skipping this winstation
  1564. // would appear as if we disconnected from every connected winstation.
  1565. continue;
  1566. }
  1567. // create a reset parameters structure
  1568. ResetParms *pResetParms = new ResetParms;
  1569. if( pResetParms != NULL )
  1570. {
  1571. pResetParms->pWinStation = pWinStation;
  1572. pResetParms->bReset = bReset;
  1573. pResetParms->bActionOnCurrentSelection = FALSE;
  1574. // Start a thread to do the reset
  1575. DBGMSG( L"TSMAN!CWinAdminDoc_ResetWinStation %s\n", pWinStation->GetName() );
  1576. AfxBeginThread((AFX_THREADPROC)CWinStation::Reset, pResetParms);
  1577. }
  1578. }
  1579. }
  1580. // Unlock the list of WinStations
  1581. pServer->UnlockWinStationList();
  1582. }
  1583. UnlockServerList();
  1584. }
  1585. } // end CWinAdminDoc::ResetWinStation
  1586. /////////////////////////////////////////////////////////////////////////////
  1587. // CWinAdminDoc::ShadowWinStation
  1588. //
  1589. // bTemp is TRUE if we are to shadow the temporarily selected tree item.
  1590. //
  1591. void CWinAdminDoc::ShadowWinStation(BOOL bTemp)
  1592. {
  1593. // Are we resetting the temporarily selected tree item?
  1594. if(bTemp) {
  1595. // Is the temporarily selected item in the tree a WinStation?
  1596. if(m_TempSelectedType == NODE_WINSTATION) {
  1597. ((CWinStation*)m_pTempSelectedNode)->Shadow();
  1598. }
  1599. return;
  1600. }
  1601. // Is the WinStation selected in the tree?
  1602. if(m_CurrentSelectedType == NODE_WINSTATION) {
  1603. ((CWinStation*)m_CurrentSelectedNode)->Shadow();
  1604. }
  1605. // Go through the list of WinStations on the currently selected server
  1606. // and send messages to those that are selected
  1607. else if(m_CurrentView == VIEW_SERVER) {
  1608. // Get a pointer to the selected server
  1609. CServer *pServer = (CServer*)m_CurrentSelectedNode;
  1610. // Lock the server's list of WinStations
  1611. pServer->LockWinStationList();
  1612. // Get a pointer to the server's list of WinStations
  1613. CObList *pWinStationList = pServer->GetWinStationList();
  1614. BOOL IsLockAlreadyReleased = FALSE;
  1615. // Iterate through the WinStation list
  1616. POSITION pos = pWinStationList->GetHeadPosition();
  1617. while(pos) {
  1618. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1619. if(pWinStation->IsSelected()) {
  1620. pServer->UnlockWinStationList();
  1621. IsLockAlreadyReleased = TRUE;
  1622. pWinStation->Shadow();
  1623. break; // we can only shadow one WinStation
  1624. }
  1625. }
  1626. // Unlock the list of WinStations
  1627. if (IsLockAlreadyReleased == FALSE) {
  1628. pServer->UnlockWinStationList();
  1629. }
  1630. }
  1631. else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
  1632. LockServerList();
  1633. POSITION pos2 = m_ServerList.GetHeadPosition();
  1634. while(pos2) {
  1635. // Get a pointer to the server
  1636. CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
  1637. // Lock the server's list of WinStations
  1638. pServer->LockWinStationList();
  1639. // Get a pointer to the server's list of WinStations
  1640. CObList *pWinStationList = pServer->GetWinStationList();
  1641. BOOL IsLockAlreadyReleased = FALSE;
  1642. // Iterate through the WinStation list
  1643. POSITION pos = pWinStationList->GetHeadPosition();
  1644. while(pos) {
  1645. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  1646. if(pWinStation->IsSelected()) {
  1647. pServer->UnlockWinStationList();
  1648. IsLockAlreadyReleased = TRUE;
  1649. pWinStation->Shadow();
  1650. break; // we can only shadow one WinStation
  1651. }
  1652. }
  1653. // Unlock the list of WinStations
  1654. if (IsLockAlreadyReleased == FALSE) {
  1655. pServer->UnlockWinStationList();
  1656. }
  1657. else
  1658. {
  1659. break; // we can only shadow one WinStation
  1660. }
  1661. }
  1662. UnlockServerList();
  1663. }
  1664. } // end CWinAdminDoc::ShadowWinStation
  1665. /////////////////////////////////////////////////////////////////////////////
  1666. // CWinAdminDoc::ServerConnect
  1667. //
  1668. void CWinAdminDoc::ServerConnect()
  1669. {
  1670. ODS( L"CWinAdminDoc::ServerConnect\n" );
  1671. // Is the Server selected in the tree?
  1672. if(m_TempSelectedType == NODE_SERVER)
  1673. {
  1674. CServer *pServer = (CServer*)m_pTempSelectedNode;
  1675. // Tell the server to connect
  1676. if ((pServer->GetState() == SS_BAD) && (pServer->HasLostConnection() || !(pServer->IsServerSane())))
  1677. {
  1678. ODS( L"\tDisconnecting from server\n" );
  1679. /* disconnect */
  1680. pServer->Disconnect( );
  1681. }
  1682. pServer->Connect();
  1683. }
  1684. else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN)
  1685. {
  1686. LockServerList();
  1687. POSITION pos = m_ServerList.GetHeadPosition();
  1688. ODS( L"\tenumerating from server list\n" );
  1689. while(pos) {
  1690. // Get a pointer to the server
  1691. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  1692. // If this Server is selected, connect to it
  1693. if( pServer->IsSelected() )
  1694. {
  1695. // Tell the server to connect
  1696. if ((pServer->GetState() == SS_BAD) && (pServer->HasLostConnection() || !(pServer->IsServerSane())))
  1697. {
  1698. ODS( L"\tDisconnecting from server\n" );
  1699. /* disconnect */
  1700. pServer->Disconnect( );
  1701. }
  1702. pServer->Connect();
  1703. }
  1704. }
  1705. UnlockServerList();
  1706. }
  1707. } // end CWinAdminDoc::ServerConnect
  1708. /////////////////////////////////////////////////////////////////////////////
  1709. // CWinAdminDoc::ServerDisconnect
  1710. //
  1711. void CWinAdminDoc::ServerDisconnect()
  1712. {
  1713. // Is the Server selected in the tree?
  1714. if(m_TempSelectedType == NODE_SERVER) {
  1715. CServer *pServer = (CServer*)m_pTempSelectedNode;
  1716. // Tell the server to disconnect
  1717. pServer->Disconnect();
  1718. }
  1719. else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
  1720. CString AString;
  1721. CDialog dlgWait;
  1722. dlgWait.Create(IDD_SHUTDOWN, NULL);
  1723. LockServerList();
  1724. // Do a first loop to signal the server background threads that they must stop
  1725. POSITION pos = m_ServerList.GetHeadPosition();
  1726. while(pos) {
  1727. // Get a pointer to the server
  1728. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  1729. // If this Server is selected, stop its background thread
  1730. if(pServer->IsSelected()) {
  1731. // thell the server background thread to stop
  1732. pServer->ClearBackgroundContinue();
  1733. }
  1734. }
  1735. // do a second loop to disconnect the servers
  1736. pos = m_ServerList.GetHeadPosition();
  1737. while(pos) {
  1738. // Get a pointer to the server
  1739. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  1740. // If this Server is selected, disconnect from it
  1741. if(pServer->IsSelected()) {
  1742. AString.Format(IDS_DISCONNECTING, pServer->GetName());
  1743. dlgWait.SetDlgItemText(IDC_SHUTDOWN_MSG, AString);
  1744. // Tell the server to disconnect
  1745. pServer->Disconnect();
  1746. }
  1747. }
  1748. UnlockServerList();
  1749. dlgWait.PostMessage(WM_CLOSE);
  1750. }
  1751. } // end CWinAdminDoc::ServerDisconnect
  1752. /////////////////////////////////////////////////////////////////////////////
  1753. // CWinAdminDoc::TempDomainConnectAllServers
  1754. //
  1755. // Connect to all the servers in temporarily selected Domain
  1756. //
  1757. void CWinAdminDoc::TempDomainConnectAllServers()
  1758. {
  1759. if(m_TempSelectedType == NODE_DOMAIN) {
  1760. ((CDomain*)m_pTempSelectedNode)->ConnectAllServers();
  1761. }
  1762. } // end CWinAdminDoc::TempDomainConnectAllServers
  1763. /////////////////////////////////////////////////////////////////////////////
  1764. // CWinAdminDoc::TempDomainDisconnectAllServers
  1765. //
  1766. // Disconnect from all servers in temporarily selected Domain
  1767. //
  1768. void CWinAdminDoc::TempDomainDisconnectAllServers()
  1769. {
  1770. if(m_TempSelectedType == NODE_DOMAIN) {
  1771. ((CDomain*)m_pTempSelectedNode)->DisconnectAllServers();
  1772. }
  1773. } // end CWinAdminDoc::TempDomainDisconnectAllServers
  1774. /////////////////////////////////////////////////////////////////////////////
  1775. // CWinAdminDoc::CurrentDomainConnectAllServers
  1776. //
  1777. // Connect to all the servers in currently selected Domain
  1778. //
  1779. void CWinAdminDoc::CurrentDomainConnectAllServers()
  1780. {
  1781. if(m_CurrentSelectedType == NODE_DOMAIN) {
  1782. ((CDomain*)m_CurrentSelectedNode)->ConnectAllServers();
  1783. }
  1784. } // end CWinAdminDoc::CurrentDomainConnectAllServers
  1785. /////////////////////////////////////////////////////////////////////////////
  1786. // CWinAdminDoc::CurrentDomainDisconnectAllServers
  1787. //
  1788. // Disconnect from all servers in currently selected Domain
  1789. //
  1790. void CWinAdminDoc::CurrentDomainDisconnectAllServers()
  1791. {
  1792. if(m_CurrentSelectedType == NODE_DOMAIN) {
  1793. ((CDomain*)m_CurrentSelectedNode)->DisconnectAllServers();
  1794. }
  1795. } // end CWinAdminDoc::CurrentDomainDisconnectAllServers
  1796. /////////////////////////////////////////////////////////////////////////////
  1797. // CWinAdminDoc::DomainFindServers
  1798. //
  1799. // Find all servers in a Domain
  1800. //
  1801. void CWinAdminDoc::DomainFindServers()
  1802. {
  1803. if(m_TempSelectedType == NODE_DOMAIN) {
  1804. CDomain *pDomain = (CDomain*)m_pTempSelectedNode;
  1805. if(!pDomain->GetThreadPointer()) pDomain->StartEnumerating();
  1806. }
  1807. } // end CWinAdminDoc::DomainFindServers
  1808. /////////////////////////////////////////////////////////////////////////////
  1809. // CWinAdminDoc::ConnectToAllServers
  1810. //
  1811. // Connect to all the servers
  1812. //
  1813. void CWinAdminDoc::ConnectToAllServers()
  1814. {
  1815. LockServerList();
  1816. POSITION pos = m_ServerList.GetHeadPosition();
  1817. while(pos) {
  1818. // Get a pointer to the server
  1819. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  1820. // If this server isn't currently connected, connect to it
  1821. if(pServer->IsState(SS_NOT_CONNECTED)) {
  1822. // Tell the server to connect
  1823. pServer->Connect();
  1824. }
  1825. }
  1826. UnlockServerList();
  1827. } // end CWinAdminDoc::ConnectToAllServers
  1828. /////////////////////////////////////////////////////////////////////////////
  1829. // CWinAdminDoc::DisconnectFromAllServers
  1830. //
  1831. // Disconnect from all the servers
  1832. //
  1833. void CWinAdminDoc::DisconnectFromAllServers()
  1834. {
  1835. CString AString;
  1836. CDialog dlgWait;
  1837. dlgWait.Create(IDD_SHUTDOWN, NULL);
  1838. // tell each domain thread to stop enumerating while we're shutting down all servers
  1839. #ifdef _STRESS_BUILD
  1840. g_fWaitForAllServersToDisconnect = 1;
  1841. #endif
  1842. POSITION pos;
  1843. LockServerList();
  1844. // Do a first loop to signal the server background threads that they must stop
  1845. pos = m_ServerList.GetHeadPosition();
  1846. while( pos )
  1847. {
  1848. // Get a pointer to the server
  1849. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  1850. // If this Server is currently connected, tell the server background thread to stop
  1851. if(pServer->GetState() != SS_NOT_CONNECTED)
  1852. {
  1853. pServer->ClearBackgroundContinue();
  1854. }
  1855. }
  1856. // do a second loop to disconnect the servers
  1857. pos = m_ServerList.GetHeadPosition();
  1858. while(pos)
  1859. {
  1860. // Get a pointer to the server
  1861. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  1862. // If this server is currently connected, disconnect from it
  1863. if(pServer->GetState() != SS_NOT_CONNECTED)
  1864. {
  1865. AString.Format(IDS_DISCONNECTING, pServer->GetName());
  1866. dlgWait.SetDlgItemText(IDC_SHUTDOWN_MSG, AString);
  1867. // Tell the server to disconnect
  1868. pServer->Disconnect();
  1869. }
  1870. }
  1871. UnlockServerList();
  1872. dlgWait.PostMessage(WM_CLOSE);
  1873. #ifdef _STRESS_BUILD
  1874. g_fWaitForAllServersToDisconnect = 0;
  1875. #endif
  1876. } // end CWinAdminDoc::DisconnectFromAllServers
  1877. /////////////////////////////////////////////////////////////////////////////
  1878. // CWinAdminDoc::FindAllServers
  1879. //
  1880. // find all Servers in all Domains
  1881. //
  1882. void CWinAdminDoc::FindAllServers()
  1883. {
  1884. if(m_bInShutdown) return;
  1885. POSITION pos = m_DomainList.GetHeadPosition();
  1886. while(pos) {
  1887. // Get a pointer to the domain
  1888. CDomain *pDomain = (CDomain*)m_DomainList.GetNext(pos);
  1889. // If this domain isn't currently enumerating servers, tell it to
  1890. if(!pDomain->GetThreadPointer()) pDomain->StartEnumerating();
  1891. }
  1892. } // end CWinAdminDoc::FindAllServers
  1893. /////////////////////////////////////////////////////////////////////////////
  1894. // CWinAdminDoc::TerminateProcess
  1895. //
  1896. void CWinAdminDoc::TerminateProcess()
  1897. {
  1898. if(m_CurrentView == VIEW_SERVER) {
  1899. // Get a pointer to the selected server
  1900. CServer *pServer = (CServer*)m_CurrentSelectedNode;
  1901. // Lock the server's list of Processes
  1902. pServer->LockProcessList();
  1903. // Get a pointer to the server's list of Processes
  1904. CObList *pProcessList = pServer->GetProcessList();
  1905. // Iterate through the Process list
  1906. POSITION pos = pProcessList->GetHeadPosition();
  1907. while(pos) {
  1908. CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
  1909. if(pProcess->IsSelected() && !pProcess->IsTerminating()) {
  1910. // Start a thread to do the terminate
  1911. AfxBeginThread((AFX_THREADPROC)CWinAdminDoc::TerminateProc, pProcess);
  1912. }
  1913. }
  1914. // Unlock the list of Processes
  1915. pServer->UnlockProcessList();
  1916. }
  1917. else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
  1918. POSITION pos2 = m_ServerList.GetHeadPosition();
  1919. while(pos2) {
  1920. // Get a pointer to the server
  1921. CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
  1922. // Lock the server's list of Processes
  1923. pServer->LockProcessList();
  1924. // Get a pointer to the server's list of Processes
  1925. CObList *pProcessList = pServer->GetProcessList();
  1926. // Iterate through the Process list
  1927. POSITION pos = pProcessList->GetHeadPosition();
  1928. while(pos) {
  1929. CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
  1930. if(pProcess->IsSelected() && !pProcess->IsTerminating()) {
  1931. // Start a thread to do the terminate
  1932. AfxBeginThread((AFX_THREADPROC)CWinAdminDoc::TerminateProc, pProcess);
  1933. }
  1934. }
  1935. // Unlock the list of Processes
  1936. pServer->UnlockProcessList();
  1937. }
  1938. }
  1939. else if(m_CurrentView == VIEW_WINSTATION) {
  1940. // Get the Server for the currently viewed WinStation
  1941. CServer *pServer = (CServer*)((CWinStation*)m_CurrentSelectedNode)->GetServer();
  1942. // Lock the server's list of Processes
  1943. pServer->LockProcessList();
  1944. // Get a pointer to the server's list of Processes
  1945. CObList *pProcessList = pServer->GetProcessList();
  1946. // Iterate through the Process list
  1947. POSITION pos = pProcessList->GetHeadPosition();
  1948. while(pos) {
  1949. CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
  1950. if(pProcess->IsSelected() && !pProcess->IsTerminating()
  1951. && (pProcess->GetWinStation() == (CWinStation*)m_CurrentSelectedNode)) {
  1952. // Start a thread to do the terminate
  1953. AfxBeginThread((AFX_THREADPROC)CWinAdminDoc::TerminateProc, pProcess);
  1954. }
  1955. }
  1956. // Unlock the list of Processes
  1957. pServer->UnlockProcessList();
  1958. }
  1959. } // end CWinAdminDoc::TerminateProcess
  1960. /////////////////////////////////////////////////////////////////////////////
  1961. // CWinAdminDoc::TerminateProc
  1962. //
  1963. UINT CWinAdminDoc::TerminateProc(LPVOID parms)
  1964. {
  1965. ASSERT(parms);
  1966. CProcess *pProcess = (CProcess*)parms;
  1967. CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
  1968. // Set the flag to say that we are trying to terminate this process
  1969. pProcess->SetTerminating();
  1970. CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
  1971. if(WinStationTerminateProcess(pProcess->GetServer()->GetHandle(),pProcess->GetPID(), 0))
  1972. {
  1973. // Send a message to remove the process from the view
  1974. if(p && ::IsWindow(p->GetSafeHwnd()))
  1975. {
  1976. p->SendMessage(WM_ADMIN_REMOVE_PROCESS, 0, (LPARAM)pProcess);
  1977. }
  1978. }
  1979. else
  1980. {
  1981. pProcess->ClearTerminating();
  1982. //Display Error Message
  1983. if(p && ::IsWindow(p->GetSafeHwnd()))
  1984. {
  1985. DWORD Error = GetLastError();
  1986. //We need this to know the length of the error message
  1987. //now that StandardErrorMessage requires that
  1988. CString tempErrorMessage;
  1989. tempErrorMessage.LoadString(IDS_CANNOT_TERMINATE);
  1990. StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
  1991. LOGONID_NONE,Error,tempErrorMessage.GetLength(),wcslen(pProcess->GetImageName()),
  1992. IDS_CANNOT_TERMINATE,pProcess->GetImageName());
  1993. }
  1994. }
  1995. return 0;
  1996. } // end CWinAdminDoc::TerminateProc
  1997. /////////////////////////////////////////////////////////////////////////////
  1998. // CWinAdminDoc::CheckConnectAllowed
  1999. //
  2000. BOOL CWinAdminDoc::CheckConnectAllowed(CWinStation *pWinStation)
  2001. {
  2002. ASSERT(pWinStation);
  2003. // If they are the same WinStation, don't let them connect
  2004. if(pWinStation->GetServer()->IsCurrentServer()
  2005. && ((CWinAdminApp*)AfxGetApp())->GetCurrentLogonId() == pWinStation->GetLogonId())
  2006. return FALSE;
  2007. if((((CWinAdminApp*)AfxGetApp())->GetCurrentWSFlags() & WDF_SHADOW_SOURCE)
  2008. && !pWinStation->HasOutstandingThreads()
  2009. && !pWinStation->IsDown()
  2010. && !pWinStation->IsListener()
  2011. && !pWinStation->IsSystemConsole()
  2012. && (pWinStation->IsDisconnected() || pWinStation->IsActive())
  2013. && pWinStation->IsOnCurrentServer())
  2014. return TRUE;
  2015. return FALSE;
  2016. } // end CWinAdminDoc::CheckConnectAllowed
  2017. /////////////////////////////////////////////////////////////////////////////
  2018. // CWinAdminDoc::CheckDisconnectAllowed
  2019. //
  2020. BOOL CWinAdminDoc::CheckDisconnectAllowed(CWinStation *pWinStation)
  2021. {
  2022. ASSERT(pWinStation);
  2023. if(!pWinStation->HasOutstandingThreads()
  2024. && !pWinStation->IsDown()
  2025. && !pWinStation->IsListener()
  2026. && !pWinStation->IsSystemConsole()
  2027. && pWinStation->IsConnected())
  2028. return TRUE;
  2029. return FALSE;
  2030. } // end CWinAdminDoc::CheckDisconnectAllowed
  2031. /////////////////////////////////////////////////////////////////////////////
  2032. // CWinAdminDoc::CheckResetAllowed
  2033. //
  2034. BOOL CWinAdminDoc::CheckResetAllowed(CWinStation *pWinStation)
  2035. {
  2036. ASSERT(pWinStation);
  2037. if(!pWinStation->HasOutstandingThreads()
  2038. && !pWinStation->IsSystemConsole())
  2039. return TRUE;
  2040. return FALSE;
  2041. } // end CWinAdminDoc::CheckResetAllowed
  2042. /////////////////////////////////////////////////////////////////////////////
  2043. // CWinAdminDoc::CheckShadowAllowed
  2044. //
  2045. BOOL CWinAdminDoc::CheckShadowAllowed(CWinStation *pWinStation)
  2046. {
  2047. ASSERT(pWinStation);
  2048. // If they are the same WinStation, don't let them shadow
  2049. if( pWinStation->GetServer()->IsCurrentServer() &&
  2050. ((CWinAdminApp*)AfxGetApp())->GetCurrentLogonId() == pWinStation->GetLogonId() )
  2051. {
  2052. return FALSE;
  2053. }
  2054. if(!pWinStation->HasOutstandingThreads() &&
  2055. !pWinStation->IsDown() && // winstation is not down
  2056. !pWinStation->IsListener() && // not a listening winstation
  2057. !pWinStation->IsDisconnected() && //not disconnected
  2058. (((CWinAdminApp*)AfxGetApp())->GetCurrentWSFlags() & WDF_SHADOW_SOURCE) && // We are valid shadow source, query winstation's wdflag in registry
  2059. (pWinStation->CanBeShadowed()) && // target can be shadow.
  2060. (pWinStation->GetState() != State_Shadow)) // target is not already in shadow
  2061. {
  2062. return TRUE;
  2063. }
  2064. return FALSE;
  2065. } // end CWinAdminDoc::CheckShadowAllowed
  2066. /////////////////////////////////////////////////////////////////////////////
  2067. // CWinAdminDoc::CheckSendMessageAllowed
  2068. //
  2069. BOOL CWinAdminDoc::CheckSendMessageAllowed(CWinStation *pWinStation)
  2070. {
  2071. ASSERT(pWinStation);
  2072. if(!pWinStation->HasOutstandingThreads()
  2073. && !pWinStation->IsDown()
  2074. && !pWinStation->IsListener()
  2075. && pWinStation->IsConnected())
  2076. return TRUE;
  2077. return FALSE;
  2078. } // end CWinAdminDoc::CheckSendMessageAllowed
  2079. /////////////////////////////////////////////////////////////////////////////
  2080. // CWinAdminDoc::CheckStatusAllowed
  2081. //
  2082. BOOL CWinAdminDoc::CheckStatusAllowed(CWinStation *pWinStation)
  2083. {
  2084. ASSERT(pWinStation);
  2085. if(!pWinStation->HasOutstandingThreads()
  2086. && !pWinStation->IsDown()
  2087. && !pWinStation->IsDisconnected()
  2088. && !pWinStation->IsIdle()
  2089. && !pWinStation->IsListener()
  2090. && !pWinStation->IsSystemConsole())
  2091. return TRUE;
  2092. return FALSE;
  2093. } // end CWinAdminDoc::CheckStatusAllowed
  2094. /////////////////////////////////////////////////////////////////////////////
  2095. // CWinAdminDoc::CheckActionAllowed
  2096. //
  2097. BOOL CWinAdminDoc::CheckActionAllowed(BOOL (*CheckFunction)(CWinStation *pWinStation), BOOL AllowMultipleSelected)
  2098. {
  2099. ASSERT(CheckFunction);
  2100. // If we are shutting down, we don't care anymore
  2101. if(m_bInShutdown) return FALSE;
  2102. // Is a WinStation selected in the tree?
  2103. if(m_CurrentSelectedType == NODE_WINSTATION)
  2104. {
  2105. CWinStation *pWinStation = (CWinStation*)m_CurrentSelectedNode;
  2106. return CheckFunction(pWinStation);
  2107. }
  2108. // We only care if the current view is Server or All Listed Servers
  2109. if(m_CurrentView == VIEW_SERVER)
  2110. {
  2111. // We need to make sure we are on the WinStation or Users page
  2112. if(m_CurrentPage != PAGE_WINSTATIONS && m_CurrentPage != PAGE_USERS)
  2113. {
  2114. return FALSE;
  2115. }
  2116. int NumSelected = 0;
  2117. CServer *pServer = (CServer*)m_CurrentSelectedNode;
  2118. // If there aren't any WinStations selected on this server, return
  2119. if(!pServer->GetNumWinStationsSelected())
  2120. {
  2121. return FALSE;
  2122. }
  2123. pServer->LockWinStationList();
  2124. CObList *pWinStationList = pServer->GetWinStationList();
  2125. // Iterate through the WinStation list
  2126. POSITION pos = pWinStationList->GetHeadPosition();
  2127. while(pos)
  2128. {
  2129. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  2130. if(pWinStation->IsSelected())
  2131. {
  2132. if(!CheckFunction(pWinStation))
  2133. {
  2134. pServer->UnlockWinStationList();
  2135. return FALSE;
  2136. }
  2137. NumSelected++;
  2138. if(!AllowMultipleSelected && NumSelected > 1)
  2139. {
  2140. pServer->UnlockWinStationList();
  2141. return FALSE;
  2142. }
  2143. }
  2144. }
  2145. pServer->UnlockWinStationList();
  2146. // If we got here, all the selected WinStations passed our criteria
  2147. if(NumSelected) return TRUE;
  2148. }
  2149. else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN)
  2150. {
  2151. // If we are doing a refresh, we can't do anything else
  2152. if(m_InRefresh) return FALSE;
  2153. // We need to make sure we are on the WinStation or Users page
  2154. if(m_CurrentPage != PAGE_AS_WINSTATIONS && m_CurrentPage != PAGE_AS_USERS
  2155. && m_CurrentPage != PAGE_DOMAIN_WINSTATIONS && m_CurrentPage != PAGE_DOMAIN_USERS)
  2156. return FALSE;
  2157. int NumSelected = 0;
  2158. LockServerList();
  2159. POSITION pos1 = m_ServerList.GetHeadPosition();
  2160. while(pos1) {
  2161. CServer *pServer = (CServer*)m_ServerList.GetNext(pos1);
  2162. // Are there any WinStations selected on this server?
  2163. if(pServer->GetNumWinStationsSelected()) {
  2164. pServer->LockWinStationList();
  2165. CObList *pWinStationList = pServer->GetWinStationList();
  2166. // Iterate through the WinStation list
  2167. POSITION pos = pWinStationList->GetHeadPosition();
  2168. while(pos) {
  2169. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  2170. if(pWinStation->IsSelected()) {
  2171. if(!CheckFunction(pWinStation)) {
  2172. pServer->UnlockWinStationList();
  2173. UnlockServerList();
  2174. return FALSE;
  2175. }
  2176. NumSelected++;
  2177. if(!AllowMultipleSelected && NumSelected > 1) {
  2178. pServer->UnlockWinStationList();
  2179. UnlockServerList();
  2180. return FALSE;
  2181. }
  2182. }
  2183. }
  2184. pServer->UnlockWinStationList();
  2185. } // end if(pServer->GetNumWinStationsSelected())
  2186. }
  2187. UnlockServerList();
  2188. // If we got this far, all the selected WinStations passed the criteria
  2189. if(NumSelected) return TRUE;
  2190. }
  2191. return FALSE;
  2192. } // end CWinAdminDoc::CheckActionAllowed
  2193. /////////////////////////////////////////////////////////////////////////////
  2194. // CWinAdminDoc::CanConnect
  2195. //
  2196. // Returns TRUE if the currently selected item in views can be Connected to
  2197. //
  2198. BOOL CWinAdminDoc::CanConnect()
  2199. {
  2200. return CheckActionAllowed(CheckConnectAllowed, FALSE);
  2201. } // end CWinAdminDoc::CanConnect
  2202. /////////////////////////////////////////////////////////////////////////////
  2203. // CWinAdminDoc::CanDisconnect
  2204. //
  2205. // Returns TRUE if the currently selected item in views can be Disconnected
  2206. //
  2207. BOOL CWinAdminDoc::CanDisconnect()
  2208. {
  2209. return CheckActionAllowed(CheckDisconnectAllowed, TRUE);
  2210. } // end CWinAdminDoc::CanDisconnect
  2211. /////////////////////////////////////////////////////////////////////////////
  2212. // CWinAdminDoc::CanReset
  2213. //
  2214. // Returns TRUE if the currently selected item in views can be Reset
  2215. //
  2216. BOOL CWinAdminDoc::CanReset()
  2217. {
  2218. return CheckActionAllowed(CheckResetAllowed, TRUE);
  2219. } // end CWinAdminDoc::CanReset
  2220. /////////////////////////////////////////////////////////////////////////////
  2221. // CWinAdminDoc::CanShadow
  2222. //
  2223. // Returns TRUE if the currently selected item in views can be Shadowed
  2224. //
  2225. BOOL CWinAdminDoc::CanShadow()
  2226. {
  2227. return CheckActionAllowed(CheckShadowAllowed, FALSE);
  2228. } // end CWinAdminDoc::CanShadow
  2229. /////////////////////////////////////////////////////////////////////////////
  2230. // CWinAdminDoc::CanSendMessage
  2231. //
  2232. // Returns TRUE if the currently selected item in views can be sent a message
  2233. //
  2234. BOOL CWinAdminDoc::CanSendMessage()
  2235. {
  2236. return CheckActionAllowed(CheckSendMessageAllowed, TRUE);
  2237. } // end CWinAdminDoc::CanSendMessage
  2238. /////////////////////////////////////////////////////////////////////////////
  2239. // CWinAdminDoc::CanStatus
  2240. //
  2241. // Returns TRUE if the currently selected item in views can show Status
  2242. //
  2243. BOOL CWinAdminDoc::CanStatus()
  2244. {
  2245. return CheckActionAllowed(CheckStatusAllowed, TRUE);
  2246. } // end CWinAdminDoc::CanStatus
  2247. /////////////////////////////////////////////////////////////////////////////
  2248. // CWinAdminDoc::CanLogoff
  2249. //
  2250. // Returns TRUE if the currently selected item in views can be Logged Off
  2251. //
  2252. BOOL CWinAdminDoc::CanLogoff()
  2253. {
  2254. // If we are shutting down, we don't care anymore
  2255. if(m_bInShutdown) return FALSE;
  2256. // Is a WinStation selected in the tree?
  2257. if(m_CurrentSelectedType == NODE_WINSTATION) {
  2258. return FALSE;
  2259. }
  2260. // We only care if the current view is Server or All Listed Servers
  2261. if(m_CurrentView == VIEW_SERVER) {
  2262. // We need to make sure we are on the Users page
  2263. if(m_CurrentPage != PAGE_USERS) return FALSE;
  2264. BOOL Answer = FALSE;
  2265. CServer *pServer = (CServer*)m_CurrentSelectedNode;
  2266. // If there aren't any WinStations selected on this server, return
  2267. if(!pServer->GetNumWinStationsSelected()) return FALSE;
  2268. pServer->LockWinStationList();
  2269. CObList *pWinStationList = pServer->GetWinStationList();
  2270. // Iterate through the WinStation list
  2271. POSITION pos = pWinStationList->GetHeadPosition();
  2272. while(pos) {
  2273. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  2274. if(pWinStation->IsSelected()) {
  2275. if(!pWinStation->HasOutstandingThreads())
  2276. Answer = TRUE;
  2277. }
  2278. }
  2279. pServer->UnlockWinStationList();
  2280. return Answer;
  2281. } else if(m_CurrentView == VIEW_ALL_SERVERS || m_CurrentView == VIEW_DOMAIN) {
  2282. // If we are doing a refesh, we can't do anything else
  2283. if(m_InRefresh) return FALSE;
  2284. // We need to make sure we are on the Users page
  2285. if(m_CurrentPage != PAGE_AS_USERS && m_CurrentPage != PAGE_DOMAIN_USERS) return FALSE;
  2286. BOOL Answer = FALSE;
  2287. LockServerList();
  2288. POSITION pos1 = m_ServerList.GetHeadPosition();
  2289. while(pos1) {
  2290. CServer *pServer = (CServer*)m_ServerList.GetNext(pos1);
  2291. // Are there any WinStations selected on this server?
  2292. if(pServer->GetNumWinStationsSelected()) {
  2293. pServer->LockWinStationList();
  2294. CObList *pWinStationList = pServer->GetWinStationList();
  2295. // Iterate through the WinStation list
  2296. POSITION pos = pWinStationList->GetHeadPosition();
  2297. while(pos) {
  2298. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  2299. if(pWinStation->IsSelected()) {
  2300. if(!pWinStation->HasOutstandingThreads())
  2301. Answer = TRUE;
  2302. }
  2303. }
  2304. pServer->UnlockWinStationList();
  2305. } // end if(pServer->GetNumWinStationsSelected())
  2306. }
  2307. UnlockServerList();
  2308. return Answer;
  2309. }
  2310. return FALSE;
  2311. } // end CWinAdminDoc::CanLogoff
  2312. /////////////////////////////////////////////////////////////////////////////
  2313. // CWinAdminDoc::CanTerminate
  2314. //
  2315. // Returns TRUE if the currently selected item in views can be Terminated
  2316. //
  2317. BOOL CWinAdminDoc::CanTerminate()
  2318. {
  2319. // If we are shutting down, we don't care anymore
  2320. if(m_bInShutdown) return FALSE;
  2321. // We have to be in All Selected Servers, Server, or WinStation view
  2322. if((m_CurrentView == VIEW_ALL_SERVERS && m_CurrentPage == PAGE_AS_PROCESSES)
  2323. || (m_CurrentView == VIEW_DOMAIN && m_CurrentPage == PAGE_DOMAIN_PROCESSES)) {
  2324. // If we are doing a refresh, we can't do anything else
  2325. if(m_InRefresh) return FALSE;
  2326. // Loop through all the servers and see if any processes are selected
  2327. LockServerList();
  2328. POSITION pos2 = m_ServerList.GetHeadPosition();
  2329. while(pos2) {
  2330. CServer *pServer = (CServer*)m_ServerList.GetNext(pos2);
  2331. // Are there any processes selected on this server?
  2332. if(pServer->GetNumProcessesSelected()) {
  2333. pServer->LockProcessList();
  2334. CObList *pProcessList = pServer->GetProcessList();
  2335. POSITION pos = pProcessList->GetHeadPosition();
  2336. while(pos) {
  2337. CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
  2338. // We only need one process to be selected
  2339. if(pProcess->IsSelected() && !pProcess->IsTerminating()) {
  2340. pServer->UnlockProcessList();
  2341. UnlockServerList();
  2342. return TRUE;
  2343. }
  2344. }
  2345. pServer->UnlockProcessList();
  2346. } // end if(pServer->GetNumProcessesSelected())
  2347. }
  2348. UnlockServerList();
  2349. return FALSE;
  2350. }
  2351. if(m_CurrentView == VIEW_SERVER && m_CurrentPage == PAGE_PROCESSES) {
  2352. CServer *pServer = (CServer*)m_CurrentSelectedNode;
  2353. // If there aren't any processes selected on this server, return
  2354. if(!pServer->GetNumProcessesSelected()) return FALSE;
  2355. pServer->LockProcessList();
  2356. CObList *pProcessList = pServer->GetProcessList();
  2357. POSITION pos = pProcessList->GetHeadPosition();
  2358. while(pos) {
  2359. CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
  2360. // We only need one process to be selected
  2361. if(pProcess->IsSelected() && !pProcess->IsTerminating()) {
  2362. pServer->UnlockProcessList();
  2363. return TRUE;
  2364. }
  2365. }
  2366. pServer->UnlockProcessList();
  2367. return FALSE;
  2368. }
  2369. if(m_CurrentView == VIEW_WINSTATION && m_CurrentPage == PAGE_WS_PROCESSES) {
  2370. CServer *pServer = (CServer*)((CWinStation*)m_CurrentSelectedNode)->GetServer();
  2371. pServer->LockProcessList();
  2372. CObList *pProcessList = pServer->GetProcessList();
  2373. POSITION pos = pProcessList->GetHeadPosition();
  2374. while(pos) {
  2375. CProcess *pProcess = (CProcess*)pProcessList->GetNext(pos);
  2376. // We only need one process to be selected
  2377. if(pProcess->IsSelected() && !pProcess->IsTerminating()) {
  2378. pServer->UnlockProcessList();
  2379. return TRUE;
  2380. }
  2381. }
  2382. pServer->UnlockProcessList();
  2383. return FALSE;
  2384. }
  2385. return FALSE;
  2386. } // end CWinAdminDoc::CanTerminate
  2387. //=--------------------------------------------------------
  2388. BOOL CWinAdminDoc::IsAlreadyFavorite( )
  2389. {
  2390. if(m_TempSelectedType == NODE_SERVER)
  2391. {
  2392. CServer *pServer = (CServer*)m_pTempSelectedNode;
  2393. if( pServer->GetTreeItemFromFav( ) != NULL )
  2394. {
  2395. return TRUE;
  2396. }
  2397. }
  2398. return FALSE;
  2399. }
  2400. /////////////////////////////////////////////////////////////////////////////
  2401. // CWinAdminDoc::CanServerConnect
  2402. //
  2403. // Returns TRUE if the currently selected server in views can be connected to
  2404. //
  2405. BOOL CWinAdminDoc::CanServerConnect()
  2406. {
  2407. // If we are shutting down, we don't care anymore
  2408. if(m_bInShutdown) return FALSE;
  2409. // Is a Server selected in the tree?
  2410. if(m_TempSelectedType == NODE_SERVER) {
  2411. if(((CServer*)m_pTempSelectedNode)->GetState() == SS_NOT_CONNECTED ||
  2412. ((CServer*)m_pTempSelectedNode)->GetState() == SS_BAD ) return TRUE;
  2413. }
  2414. // Is a Server selected in the tree?
  2415. else if(m_CurrentSelectedType == NODE_SERVER) {
  2416. if(((CServer*)m_CurrentSelectedNode)->GetState() == SS_NOT_CONNECTED ||
  2417. ((CServer*)m_CurrentSelectedNode)->GetState() == SS_BAD ) return TRUE;
  2418. }
  2419. // We only care if the current view is Domain or All Listed Servers
  2420. else if(m_CurrentView == VIEW_DOMAIN) {
  2421. // We need to make sure we are on the Servers page
  2422. if(m_CurrentPage != PAGE_DOMAIN_SERVERS) return FALSE;
  2423. int NumSelected = 0;
  2424. CDomain *pDomain = (CDomain*)m_CurrentSelectedNode;
  2425. LockServerList();
  2426. // Iterate through the Server list
  2427. POSITION pos = m_ServerList.GetHeadPosition();
  2428. while(pos) {
  2429. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  2430. if(pServer->IsSelected() && pServer->GetDomain() == pDomain) {
  2431. if(!pServer->IsState(SS_NOT_CONNECTED)) {
  2432. UnlockServerList();
  2433. return FALSE;
  2434. }
  2435. NumSelected++;
  2436. }
  2437. }
  2438. UnlockServerList();
  2439. // If we got here, all the selected Servers passed our criteria
  2440. if(NumSelected) return TRUE;
  2441. }
  2442. else if(m_CurrentView == VIEW_ALL_SERVERS) {
  2443. // We need to make sure we are on the Servers page
  2444. if(m_CurrentPage != PAGE_AS_SERVERS) return FALSE;
  2445. int NumSelected = 0;
  2446. LockServerList();
  2447. // Iterate through the Server list
  2448. POSITION pos = m_ServerList.GetHeadPosition();
  2449. while(pos) {
  2450. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  2451. if(pServer->IsSelected()) {
  2452. if(!pServer->IsState(SS_NOT_CONNECTED)) {
  2453. UnlockServerList();
  2454. return FALSE;
  2455. }
  2456. NumSelected++;
  2457. }
  2458. }
  2459. UnlockServerList();
  2460. // If we got here, all the selected Servers passed our criteria
  2461. if(NumSelected) return TRUE;
  2462. }
  2463. return FALSE;
  2464. } // end CWinAdminDoc::CanServerConnect
  2465. /////////////////////////////////////////////////////////////////////////////
  2466. // CWinAdminDoc::CanServerDisconnect
  2467. //
  2468. // Returns TRUE if the currently selected server in views can be disconnected from
  2469. //
  2470. BOOL CWinAdminDoc::CanServerDisconnect()
  2471. {
  2472. // If we are shutting down, we don't care anymore
  2473. if(m_bInShutdown) return FALSE;
  2474. // Is a Server selected in the tree?
  2475. if(m_TempSelectedType == NODE_SERVER) {
  2476. if(((CServer*)m_pTempSelectedNode)->GetState() == SS_GOOD) return TRUE;
  2477. }
  2478. // Is a Server selected in the tree?
  2479. else if(m_CurrentSelectedType == NODE_SERVER) {
  2480. if(((CServer*)m_CurrentSelectedNode)->GetState() == SS_GOOD) return TRUE;
  2481. }
  2482. // We only care if the current view is Domain or All Listed Servers
  2483. else if(m_CurrentView == VIEW_DOMAIN) {
  2484. // We need to make sure we are on the Servers page
  2485. if(m_CurrentPage != PAGE_DOMAIN_SERVERS) return FALSE;
  2486. int NumSelected = 0;
  2487. CDomain *pDomain = (CDomain*)m_CurrentSelectedNode;
  2488. LockServerList();
  2489. // Iterate through the Server list
  2490. POSITION pos = m_ServerList.GetHeadPosition();
  2491. while(pos) {
  2492. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  2493. if(pServer->IsSelected() && pServer->GetDomain() == pDomain) {
  2494. if(!pServer->IsState(SS_GOOD)) {
  2495. UnlockServerList();
  2496. return FALSE;
  2497. }
  2498. NumSelected++;
  2499. }
  2500. }
  2501. UnlockServerList();
  2502. // If we got here, all the selected Servers passed our criteria
  2503. if(NumSelected) return TRUE;
  2504. }
  2505. else if(m_CurrentView == VIEW_ALL_SERVERS) {
  2506. // We need to make sure we are on the Servers page
  2507. if(m_CurrentPage != PAGE_AS_SERVERS) return FALSE;
  2508. int NumSelected = 0;
  2509. LockServerList();
  2510. // Iterate through the Server list
  2511. POSITION pos = m_ServerList.GetHeadPosition();
  2512. while(pos) {
  2513. CServer *pServer = (CServer*)m_ServerList.GetNext(pos);
  2514. if(pServer->IsSelected()) {
  2515. if(!pServer->IsState(SS_GOOD)) {
  2516. UnlockServerList();
  2517. return FALSE;
  2518. }
  2519. NumSelected++;
  2520. }
  2521. }
  2522. UnlockServerList();
  2523. // If we got here, all the selected Servers passed our criteria
  2524. if(NumSelected) return TRUE;
  2525. }
  2526. return FALSE;
  2527. } // end CWinAdminDoc::CanServerDisconnect
  2528. /////////////////////////////////////////////////////////////////////////////
  2529. // CWinAdminDoc::CanTempConnect
  2530. //
  2531. // Returns TRUE if the temporarily selected item in views can be Connected to
  2532. //
  2533. BOOL CWinAdminDoc::CanTempConnect()
  2534. {
  2535. // If we are shutting down, we don't care anymore
  2536. if(m_bInShutdown) return FALSE;
  2537. // Is a WinStation selected in the tree?
  2538. if(m_TempSelectedType == NODE_WINSTATION) {
  2539. return CheckConnectAllowed((CWinStation*)m_pTempSelectedNode);
  2540. }
  2541. return FALSE;
  2542. } // end CWinAdminDoc::CanTempConnect
  2543. /////////////////////////////////////////////////////////////////////////////
  2544. // CWinAdminDoc::CanTempDisconnect
  2545. //
  2546. // Returns TRUE if the temporarily selected item in views can be Disconnected
  2547. //
  2548. BOOL CWinAdminDoc::CanTempDisconnect()
  2549. {
  2550. // If we are shutting down, we don't care anymore
  2551. if(m_bInShutdown) return FALSE;
  2552. // Is a WinStation selected in the tree?
  2553. if(m_TempSelectedType == NODE_WINSTATION) {
  2554. return CheckDisconnectAllowed((CWinStation*)m_pTempSelectedNode);
  2555. }
  2556. return FALSE;
  2557. } // end CWinAdminDoc::CanTempDisconnect
  2558. /////////////////////////////////////////////////////////////////////////////
  2559. // CWinAdminDoc::CanTempReset
  2560. //
  2561. // Returns TRUE if the temporarily selected item in views can be Reset
  2562. //
  2563. BOOL CWinAdminDoc::CanTempReset()
  2564. {
  2565. // If we are shutting down, we don't care anymore
  2566. if(m_bInShutdown) return FALSE;
  2567. // Is a WinStation selected in the tree?
  2568. if(m_TempSelectedType == NODE_WINSTATION)
  2569. {
  2570. // If the winstation we're working on disappears before we get here
  2571. // then just return
  2572. if (m_CurrentSelectedType == NODE_WINSTATION)
  2573. {
  2574. return CheckResetAllowed((CWinStation*)m_pTempSelectedNode);
  2575. }
  2576. }
  2577. return FALSE;
  2578. } // end CWinAdminDoc::CanTempReset
  2579. /////////////////////////////////////////////////////////////////////////////
  2580. // CWinAdminDoc::CanTempShadow
  2581. //
  2582. // Returns TRUE if the temporarily selected item in views can be Shadowed
  2583. //
  2584. BOOL CWinAdminDoc::CanTempShadow()
  2585. {
  2586. // If we are shutting down, we don't care anymore
  2587. if(m_bInShutdown) return FALSE;
  2588. // Is a WinStation selected in the tree?
  2589. if(m_TempSelectedType == NODE_WINSTATION) {
  2590. return CheckShadowAllowed((CWinStation*)m_pTempSelectedNode);
  2591. }
  2592. return FALSE;
  2593. } // end CWinAdminDoc::CanTempShadow
  2594. /////////////////////////////////////////////////////////////////////////////
  2595. // CWinAdminDoc::CanTempSendMessage
  2596. //
  2597. // Returns TRUE if the temporarily selected item in views can be sent a message
  2598. //
  2599. BOOL CWinAdminDoc::CanTempSendMessage()
  2600. {
  2601. // If we are shutting down, we don't care anymore
  2602. if(m_bInShutdown) return FALSE;
  2603. // Is a WinStation selected in the tree?
  2604. if(m_TempSelectedType == NODE_WINSTATION) {
  2605. return CheckSendMessageAllowed((CWinStation*)m_pTempSelectedNode);
  2606. }
  2607. return FALSE;
  2608. } // end CWinAdminDoc::CanTempSendMessage
  2609. /////////////////////////////////////////////////////////////////////////////
  2610. // CWinAdminDoc::CanTempStatus
  2611. //
  2612. // Returns TRUE if the temporarily selected item in views can show Status
  2613. //
  2614. BOOL CWinAdminDoc::CanTempStatus()
  2615. {
  2616. // If we are shutting down, we don't care anymore
  2617. if(m_bInShutdown) return FALSE;
  2618. // Is a WinStation selected in the tree?
  2619. if(m_TempSelectedType == NODE_WINSTATION) {
  2620. return CheckStatusAllowed((CWinStation*)m_pTempSelectedNode);
  2621. }
  2622. return FALSE;
  2623. } // end CWinAdminDoc::CanTempStatus
  2624. /////////////////////////////////////////////////////////////////////////////
  2625. // CWinAdminDoc::CanTempDomainConnect
  2626. //
  2627. // Returns TRUE if the temporarily selected Domain in tree can have all it's
  2628. // Servers connected/disconnected to/from.
  2629. //
  2630. BOOL CWinAdminDoc::CanTempDomainConnect()
  2631. {
  2632. // If we are shutting down, we don't care anymore
  2633. if(m_bInShutdown) return FALSE;
  2634. // Is a Domain selected in the tree?
  2635. if(m_TempSelectedType == NODE_DOMAIN) {
  2636. if(((CDomain*)m_pTempSelectedNode)->IsState(DS_ENUMERATING))
  2637. return TRUE;
  2638. }
  2639. return FALSE;
  2640. } // end CWinAdminDoc::CanTempDomainConnect
  2641. /////////////////////////////////////////////////////////////////////////////
  2642. // CWinAdminDoc::CanTempDomainFindServers
  2643. //
  2644. // Returns TRUE if the temporarily selected Domain in tree can go out
  2645. // and find Servers
  2646. //
  2647. BOOL CWinAdminDoc::CanTempDomainFindServers()
  2648. {
  2649. // If we are shutting down, we don't care anymore
  2650. if(m_bInShutdown) return FALSE;
  2651. // Is a Domain selected in the tree?
  2652. if(m_TempSelectedType == NODE_DOMAIN) {
  2653. if(!((CDomain*)m_pTempSelectedNode)->GetThreadPointer())
  2654. return TRUE;
  2655. }
  2656. return FALSE;
  2657. } // end CWinAdminDoc::CanTempDomainFindServers
  2658. /////////////////////////////////////////////////////////////////////////////
  2659. // CWinAdminDoc::CanDomainConnect
  2660. //
  2661. // Returns TRUE if the currently selected Domain in tree can have all it's
  2662. // Servers connected/disconnected to/from.
  2663. //
  2664. BOOL CWinAdminDoc::CanDomainConnect()
  2665. {
  2666. // If we are shutting down, we don't care anymore
  2667. if(m_bInShutdown) return FALSE;
  2668. // Is a Domain selected in the tree?
  2669. if(m_CurrentSelectedType == NODE_DOMAIN) {
  2670. if(((CDomain*)m_CurrentSelectedNode)->IsState(DS_ENUMERATING))
  2671. return TRUE;
  2672. }
  2673. return FALSE;
  2674. } // end CWinAdminDoc::CanDomainConnect
  2675. //------------------------------------------------------------------------------
  2676. void CWinAdminDoc::ServerAddToFavorites( BOOL bAdd )
  2677. {
  2678. ODS( L"CWinAdminDoc::ServerAddToFavorites\n");
  2679. // we got here from a context menu selection
  2680. CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
  2681. if(m_TempSelectedType == NODE_SERVER && pDoc != NULL )
  2682. {
  2683. CServer* pServer = ( CServer* )m_pTempSelectedNode;
  2684. if( pServer != NULL )
  2685. {
  2686. // test to see if the server is being removed
  2687. if( pServer->IsState(SS_DISCONNECTING) )
  2688. {
  2689. ODS( L"=-sneaky popup menu was up when server went away\n=-not adding server to favs\n");
  2690. return;
  2691. }
  2692. CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
  2693. if( p !=NULL && ::IsWindow(p->GetSafeHwnd() ) )
  2694. {
  2695. // ok we're off to treeview ville
  2696. if( bAdd )
  2697. {
  2698. p->SendMessage(WM_ADMIN_ADDSERVERTOFAV , 0 , (LPARAM)pServer);
  2699. }
  2700. else
  2701. {
  2702. p->SendMessage( WM_ADMIN_REMOVESERVERFROMFAV, 0 , (LPARAM)pServer);
  2703. }
  2704. }
  2705. }
  2706. }
  2707. }
  2708. //////////////////////////////////////////////////////////////////////////////////////////
  2709. //
  2710. // CWinStation Member Functions
  2711. //
  2712. //////////////////////////////////////////////////////////////////////////////////////////
  2713. /////////////////////////////////////////////////////////////////////////////
  2714. // CWinStation::CWinStation
  2715. //
  2716. CWinStation::CWinStation(CServer *pServer, PLOGONID pLogonId)
  2717. {
  2718. ASSERT(pServer);
  2719. m_WinStationFlags = 0L;
  2720. m_OutstandingThreads = 0;
  2721. m_hTreeItem = NULL;
  2722. m_hFavTree = NULL;
  2723. m_hTreeThisComputer = NULL;
  2724. m_pWd = NULL;
  2725. m_UserName[0] = '\0';
  2726. m_WdName[0] = '\0';
  2727. m_ClientName[0] = '\0';
  2728. m_Comment[0] = '\0';
  2729. m_SdClass = SdNone;
  2730. m_LogonTime.HighPart = 0L;
  2731. m_LogonTime.LowPart = 0L;
  2732. m_LastInputTime.HighPart = 0L;
  2733. m_LastInputTime.LowPart = 0L;
  2734. m_CurrentTime.HighPart = 0L;
  2735. m_CurrentTime.LowPart = 0L;
  2736. m_IdleTime.days = 0;
  2737. m_IdleTime.hours = 0;
  2738. m_IdleTime.minutes = 0;
  2739. m_IdleTime.seconds = 0;
  2740. m_pExtensionInfo = NULL;
  2741. m_pExtWinStationInfo = NULL;
  2742. m_pExtModuleInfo = NULL;
  2743. m_NumModules = 0;
  2744. m_ProtocolType = 0;
  2745. m_clientDigProductId[0] = '\0';
  2746. SetCurrent();
  2747. m_pServer = pServer;
  2748. m_LogonId = pLogonId->LogonId;
  2749. wcscpy(m_Name, pLogonId->WinStationName);
  2750. m_State = pLogonId->State;
  2751. m_SortOrder = SortOrder[pLogonId->State];
  2752. HANDLE Handle = m_pServer->GetHandle();
  2753. CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
  2754. ULONG Length;
  2755. PDCONFIG PdConfig;
  2756. if(WinStationQueryInformation(Handle, m_LogonId, WinStationPd, &PdConfig,
  2757. sizeof(PDCONFIG), &Length)) {
  2758. m_SdClass = PdConfig.Create.SdClass;
  2759. wcscpy(m_PdName, PdConfig.Create.PdName);
  2760. if(m_SdClass == SdAsync) {
  2761. CDCONFIG CdConfig;
  2762. if(WinStationQueryInformation(Handle, m_LogonId, WinStationCd, &CdConfig,
  2763. sizeof(CDCONFIG), &Length)) {
  2764. if(CdConfig.CdClass != CdModem) SetDirectAsync();
  2765. }
  2766. }
  2767. }
  2768. WDCONFIG WdConfig;
  2769. if(WinStationQueryInformation(Handle, m_LogonId, WinStationWd, &WdConfig,
  2770. sizeof(WDCONFIG), &Length)) {
  2771. wcscpy(m_WdName, WdConfig.WdName);
  2772. m_pWd = pDoc->FindWdByName(m_WdName);
  2773. // if(WdConfig.WdFlag & WDF_SHADOW_TARGET) SetCanBeShadowed();
  2774. WINSTATIONCLIENT WsClient;
  2775. if(WinStationQueryInformation(Handle, m_LogonId, WinStationClient, &WsClient,
  2776. sizeof(WINSTATIONCLIENT), &Length)) {
  2777. wcscpy(m_ClientName, WsClient.ClientName);
  2778. wcscpy(m_clientDigProductId, WsClient.clientDigProductId);
  2779. }
  2780. }
  2781. WINSTATIONCONFIG WsConfig;
  2782. if(WinStationQueryInformation(Handle, m_LogonId, WinStationConfiguration,
  2783. &WsConfig, sizeof(WINSTATIONCONFIG), &Length)) {
  2784. wcscpy(m_Comment, WsConfig.Comment);
  2785. if(WdConfig.WdFlag & WDF_SHADOW_TARGET)
  2786. {
  2787. //
  2788. // WHY we have IsDisconnected() then IsConnected() ?
  2789. // WHY we don't allow shadowing view only session
  2790. //
  2791. if( (!((IsDisconnected()) &&
  2792. ((WsConfig.User.Shadow == Shadow_EnableInputNotify) ||
  2793. (WsConfig.User.Shadow == Shadow_EnableNoInputNotify))))
  2794. || (IsConnected()) )
  2795. {
  2796. SetCanBeShadowed();
  2797. }
  2798. }
  2799. }
  2800. WINSTATIONINFORMATION WsInfo;
  2801. if(WinStationQueryInformation(Handle, m_LogonId, WinStationInformation, &WsInfo,
  2802. sizeof(WINSTATIONINFORMATION), &Length))
  2803. {
  2804. // the state may have already changed
  2805. m_State = WsInfo.ConnectState;
  2806. wcscpy(m_UserName, WsInfo.UserName);
  2807. m_LogonTime = WsInfo.LogonTime;
  2808. m_LastInputTime = IsActive() ? WsInfo.LastInputTime : WsInfo.DisconnectTime;
  2809. m_CurrentTime = WsInfo.CurrentTime;
  2810. // Calculate elapsed time
  2811. if((IsActive() || IsDisconnected()) && m_LastInputTime.QuadPart <= m_CurrentTime.QuadPart && m_LastInputTime.QuadPart)
  2812. {
  2813. LARGE_INTEGER DiffTime = CalculateDiffTime(m_LastInputTime, m_CurrentTime);
  2814. ULONG_PTR d_time = ( ULONG_PTR )DiffTime.QuadPart;
  2815. ELAPSEDTIME IdleTime;
  2816. // Calculate the days, hours, minutes, seconds since specified time.
  2817. IdleTime.days = (USHORT)(d_time / 86400L); // days since
  2818. d_time = d_time % 86400L; // seconds => partial day
  2819. IdleTime.hours = (USHORT)(d_time / 3600L); // hours since
  2820. d_time = d_time % 3600L; // seconds => partial hour
  2821. IdleTime.minutes = (USHORT)(d_time / 60L); // minutes since
  2822. IdleTime.seconds = (USHORT)(d_time % 60L);// seconds remaining
  2823. m_IdleTime = IdleTime;
  2824. TCHAR IdleTimeString[MAX_ELAPSED_TIME_LENGTH];
  2825. ElapsedTimeString( &IdleTime, FALSE, IdleTimeString);
  2826. }
  2827. }
  2828. WINSTATIONCLIENT ClientData;
  2829. // Get the protocol this WinStation is using
  2830. if(WinStationQueryInformation( Handle,
  2831. m_LogonId,
  2832. WinStationClient,
  2833. &ClientData,
  2834. sizeof(WINSTATIONCLIENT),
  2835. &Length ) ) {
  2836. m_ProtocolType = ClientData.ProtocolType;
  2837. m_EncryptionLevel = ClientData.EncryptionLevel;
  2838. }
  2839. // If there is a user, set a flag bit
  2840. if(wcslen(m_UserName)) SetHasUser();
  2841. else ClearHasUser();
  2842. // Remember when we got this information
  2843. SetLastUpdateClock();
  2844. SetQueriesSuccessful();
  2845. // If there is an extension DLL loaded, allow it to add it's own info for this WinStation
  2846. LPFNEXWINSTATIONINITPROC InitProc = ((CWinAdminApp*)AfxGetApp())->GetExtWinStationInitProc();
  2847. if(InitProc) {
  2848. m_pExtensionInfo = (*InitProc)(Handle, m_LogonId);
  2849. if(m_pExtensionInfo) {
  2850. LPFNEXGETWINSTATIONINFOPROC InfoProc = ((CWinAdminApp*)AfxGetApp())->GetExtGetWinStationInfoProc();
  2851. if(InfoProc) {
  2852. m_pExtWinStationInfo = (*InfoProc)(m_pExtensionInfo);
  2853. }
  2854. }
  2855. }
  2856. } // end CWinStation::CWinStation
  2857. /////////////////////////////////////////////////////////////////////////////
  2858. // CWinStation::~CWinStation
  2859. //
  2860. CWinStation::~CWinStation()
  2861. {
  2862. // Remove all of the processes attributed to this WinStation
  2863. // from the Server's list
  2864. m_pServer->RemoveWinStationProcesses(this);
  2865. // If there is an extension DLL, let it cleanup anything it added to this WinStation
  2866. LPFNEXWINSTATIONCLEANUPPROC CleanupProc = ((CWinAdminApp*)AfxGetApp())->GetExtWinStationCleanupProc();
  2867. if(CleanupProc) {
  2868. (*CleanupProc)(m_pExtensionInfo);
  2869. }
  2870. if(m_pExtModuleInfo) {
  2871. // Get the extension DLL's function to free the module info
  2872. LPFNEXFREEWINSTATIONMODULESPROC FreeModulesProc = ((CWinAdminApp*)AfxGetApp())->GetExtFreeWinStationModulesProc();
  2873. if(FreeModulesProc) {
  2874. (*FreeModulesProc)(m_pExtModuleInfo);
  2875. } else {
  2876. TRACE0("WAExGetWinStationModules exists without WAExFreeWinStationModules\n");
  2877. ASSERT(0);
  2878. }
  2879. }
  2880. } // end CWinStation::~CWinStation
  2881. /////////////////////////////////////////////////////////////////////////////
  2882. // CWinStation::Update
  2883. //
  2884. // Updates this WinStation with new data from another CWinStation
  2885. //
  2886. BOOL CWinStation::Update(CWinStation *pWinStation)
  2887. {
  2888. ASSERT(pWinStation);
  2889. // Check for any information that has changed
  2890. BOOL bInfoChanged = FALSE;
  2891. // Check the State
  2892. if(m_State != pWinStation->GetState()) {
  2893. // If the old state was disconnected, then we want to
  2894. // go out and get the module (client) information again
  2895. if(m_State == State_Disconnected)
  2896. ClearAdditionalDone();
  2897. m_State = pWinStation->GetState();
  2898. // Sort order only changes when state changes
  2899. m_SortOrder = pWinStation->GetSortOrder();
  2900. bInfoChanged = TRUE;
  2901. }
  2902. // Check the UserName
  2903. if(wcscmp(m_UserName, pWinStation->GetUserName()) != 0) {
  2904. SetUserName(pWinStation->GetUserName());
  2905. if(pWinStation->HasUser()) SetHasUser();
  2906. else ClearHasUser();
  2907. bInfoChanged = TRUE;
  2908. }
  2909. // Check the SdClass
  2910. if(m_SdClass != pWinStation->GetSdClass()) {
  2911. m_SdClass = pWinStation->GetSdClass();
  2912. bInfoChanged = TRUE;
  2913. }
  2914. // Check the Comment
  2915. if(wcscmp(m_Comment, pWinStation->GetComment()) != 0) {
  2916. SetComment(pWinStation->GetComment());
  2917. bInfoChanged = TRUE;
  2918. }
  2919. // Check the WdName
  2920. if(wcscmp(m_WdName, pWinStation->GetWdName()) != 0) {
  2921. SetWdName(pWinStation->GetWdName());
  2922. SetWd(pWinStation->GetWd());
  2923. bInfoChanged = TRUE;
  2924. }
  2925. // Check the Encryption Level
  2926. if (GetEncryptionLevel() != pWinStation->GetEncryptionLevel() ) {
  2927. SetEncryptionLevel(pWinStation->GetEncryptionLevel());
  2928. bInfoChanged = TRUE;
  2929. }
  2930. // Check the Name
  2931. if(wcscmp(m_Name, pWinStation->GetName()) != 0) {
  2932. SetName(pWinStation->GetName());
  2933. bInfoChanged = TRUE;
  2934. }
  2935. // Check the Client Name
  2936. if(wcscmp(m_ClientName, pWinStation->GetClientName()) != 0) {
  2937. SetClientName(pWinStation->GetClientName());
  2938. bInfoChanged = TRUE;
  2939. }
  2940. if(wcscmp(m_clientDigProductId, pWinStation->GetClientDigProductId()) != 0) {
  2941. SetClientDigProductId(pWinStation->GetClientDigProductId());
  2942. bInfoChanged = TRUE;
  2943. }
  2944. // Always copy the LastInputTime
  2945. SetLastInputTime(pWinStation->GetLastInputTime());
  2946. // Always copy the CurrentTime
  2947. SetCurrentTime(pWinStation->GetCurrentTime());
  2948. // Always copy the LogonTime
  2949. // (The logon time is not set when we create a CWinStation on the fly)
  2950. SetLogonTime(pWinStation->GetLogonTime());
  2951. // Always copy the IdleTime
  2952. SetIdleTime(pWinStation->GetIdleTime());
  2953. // Always copy the Can Shadow flag
  2954. if(pWinStation->CanBeShadowed()) SetCanBeShadowed();
  2955. // Copy the Extension Info pointer if necessary
  2956. if(pWinStation->GetExtensionInfo() && !m_pExtensionInfo) {
  2957. m_pExtensionInfo = pWinStation->GetExtensionInfo();
  2958. pWinStation->SetExtensionInfo(NULL);
  2959. }
  2960. // Copy the Extended Info pointer if necessary
  2961. if(pWinStation->GetExtendedInfo() && !m_pExtWinStationInfo) {
  2962. m_pExtWinStationInfo = pWinStation->GetExtendedInfo();
  2963. pWinStation->SetExtendedInfo(NULL);
  2964. }
  2965. // If this guy hasn't been updated in a while, do it now
  2966. if(!bInfoChanged) {
  2967. clock_t now = clock();
  2968. if((now - GetLastUpdateClock()) > 30)
  2969. bInfoChanged = TRUE;
  2970. }
  2971. if(bInfoChanged) {
  2972. SetChanged();
  2973. SetLastUpdateClock();
  2974. }
  2975. return bInfoChanged;
  2976. } // end CWinStation::Update
  2977. /////////////////////////////////////////////////////////////////////////////
  2978. // CWinStation::Connect
  2979. //
  2980. void CWinStation::Connect(BOOL bUser)
  2981. {
  2982. TCHAR szPassword[PASSWORD_LENGTH+1];
  2983. BOOL bFirstTime = TRUE;
  2984. DWORD Error;
  2985. HANDLE hServer = m_pServer->GetHandle();
  2986. // Start the connect loop with null password to try first.
  2987. szPassword[0] = '\0';
  2988. while(1) {
  2989. if(WinStationConnect(hServer, m_LogonId, LOGONID_CURRENT, szPassword, TRUE))
  2990. break; // success - break out of loop
  2991. if(((Error = GetLastError()) != ERROR_LOGON_FAILURE) || !bFirstTime ) {
  2992. //We need this to know the length of the error message
  2993. //now that StandardErrorMessage requires that
  2994. CString tempErrorMessage;
  2995. tempErrorMessage.LoadString(IDS_ERR_CONNECT);
  2996. StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
  2997. m_LogonId, Error, tempErrorMessage.GetLength(), 10, IDS_ERR_CONNECT, m_LogonId);
  2998. }
  2999. // If a 'logon failure' brought us here, issue password dialog.
  3000. // Otherwise, break the connect loop.
  3001. if(Error == ERROR_LOGON_FAILURE) {
  3002. CPasswordDlg CPDlg;
  3003. CPDlg.SetDialogMode(bUser ? PwdDlg_UserMode : PwdDlg_WinStationMode);
  3004. if(CPDlg.DoModal() == IDOK ) {
  3005. lstrcpy(szPassword, CPDlg.GetPassword());
  3006. } else {
  3007. break; // user CANCEL: break connect loop
  3008. }
  3009. } else
  3010. break; // other error: break connect loop
  3011. // the next time through the loop won't be the first
  3012. bFirstTime = FALSE;
  3013. }
  3014. SecureZeroMemory((PVOID)szPassword , sizeof(szPassword));
  3015. return;
  3016. } // end CWinStation::Connect
  3017. /////////////////////////////////////////////////////////////////////////////
  3018. // CWinStation::ShowStatus
  3019. //
  3020. void CWinStation::ShowStatus()
  3021. {
  3022. switch(m_SdClass) {
  3023. case SdNetwork:
  3024. case SdNasi:
  3025. new CNetworkStatusDlg(this);
  3026. break;
  3027. case SdAsync:
  3028. new CAsyncStatusDlg(this);
  3029. break;
  3030. default:
  3031. break;
  3032. }
  3033. } // end CWinStation::ShowStatus
  3034. /////////////////////////////////////////////////////////////////////////////
  3035. // CWinStation::Shadow
  3036. //
  3037. void CWinStation::Shadow()
  3038. {
  3039. WINSTATIONCONFIG WSConfig;
  3040. SHADOWCLASS Shadow;
  3041. ULONG ReturnLength;
  3042. DWORD ShadowError;
  3043. HANDLE hServer = m_pServer->GetHandle();
  3044. // Determine the WinStation's shadow state.
  3045. if(!WinStationQueryInformation(hServer,
  3046. m_LogonId,
  3047. WinStationConfiguration,
  3048. &WSConfig, sizeof(WINSTATIONCONFIG),
  3049. &ReturnLength ) ) {
  3050. // Can't query WinStation configuration; complain and return
  3051. return;
  3052. }
  3053. Shadow = WSConfig.User.Shadow;
  3054. // If shadowing is disabled, let the user know and return
  3055. if(Shadow == Shadow_Disable ) {
  3056. DWORD Error = GetLastError();
  3057. //We need this to know the length of the error message
  3058. //now that StandardErrorMessage requires that
  3059. CString tempErrorMessage;
  3060. tempErrorMessage.LoadString(IDS_ERR_SHADOW_DISABLED);
  3061. StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
  3062. m_LogonId, Error, tempErrorMessage.GetLength(), 10, IDS_ERR_SHADOW_DISABLED, m_LogonId);
  3063. return;
  3064. }
  3065. // If the WinStation is disconnected and shadow notify is 'on',
  3066. // let the user know and break out.
  3067. if((m_State == State_Disconnected) &&
  3068. ((Shadow == Shadow_EnableInputNotify) ||
  3069. (Shadow == Shadow_EnableNoInputNotify)) ) {
  3070. DWORD Error = GetLastError();
  3071. //We need this to know the length of the error message
  3072. //now that StandardErrorMessage requires that
  3073. CString tempErrorMessage;
  3074. tempErrorMessage.LoadString(IDS_ERR_SHADOW_DISCONNECTED_NOTIFY_ON);
  3075. StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
  3076. m_LogonId, Error, tempErrorMessage.GetLength(), 10, IDS_ERR_SHADOW_DISCONNECTED_NOTIFY_ON, m_LogonId);
  3077. return;
  3078. }
  3079. // Display the 'start shadow' dialog for hotkey reminder and
  3080. // final 'ok' prior to shadowing.
  3081. CShadowStartDlg SSDlg;
  3082. SSDlg.m_ShadowHotkeyKey = ((CWinAdminApp*)AfxGetApp())->GetShadowHotkeyKey();
  3083. SSDlg.m_ShadowHotkeyShift = ((CWinAdminApp*)AfxGetApp())->GetShadowHotkeyShift();
  3084. if(SSDlg.DoModal() != IDOK) {
  3085. return;
  3086. }
  3087. // launch UI thread.
  3088. DWORD tid;
  3089. HANDLE hThread = ::CreateThread( NULL , 0 , ( LPTHREAD_START_ROUTINE )Shadow_WarningProc , ( LPVOID )AfxGetInstanceHandle() , 0 , &tid );
  3090. ((CWinAdminApp*)AfxGetApp())->SetShadowHotkeyKey(SSDlg.m_ShadowHotkeyKey);
  3091. ((CWinAdminApp*)AfxGetApp())->SetShadowHotkeyShift(SSDlg.m_ShadowHotkeyShift);
  3092. // Invoke the shadow DLL.
  3093. CWaitCursor Nikki;
  3094. // allow UI thread to init window
  3095. Sleep( 900 );
  3096. // Shadow API always connects to local server,
  3097. // passing target servername as a parameter.
  3098. BOOL bOK = WinStationShadow(SERVERNAME_CURRENT, m_pServer->GetName(), m_LogonId,
  3099. (BYTE)((CWinAdminApp*)AfxGetApp())->GetShadowHotkeyKey(),
  3100. (WORD)((CWinAdminApp*)AfxGetApp())->GetShadowHotkeyShift());
  3101. if (!bOK)
  3102. {
  3103. ShadowError = GetLastError();
  3104. }
  3105. if( g_hwndShadowWarn != NULL )
  3106. {
  3107. OutputDebugString( L"Posting WM_DESTROY to dialog\n");
  3108. EndDialog( g_hwndShadowWarn , 0 );
  3109. //PostMessage( g_hwndShadowWarn , WM_CLOSEDIALOG , 0 , 0 );
  3110. }
  3111. if( !bOK )
  3112. {
  3113. //We need this to know the length of the error message
  3114. //now that StandardErrorMessage requires that
  3115. CString tempErrorMessage;
  3116. tempErrorMessage.LoadString(IDS_ERR_SHADOW);
  3117. StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
  3118. m_LogonId, ShadowError, tempErrorMessage.GetLength(), 10, IDS_ERR_SHADOW, m_LogonId);
  3119. }
  3120. CloseHandle( hThread );
  3121. } // end CWinStation::Shadow
  3122. /////////////////////////////////////////////////////////////////////////////
  3123. // CWinStation::SendMessage
  3124. //
  3125. UINT CWinStation::SendMessage(LPVOID pParam)
  3126. {
  3127. ASSERT(pParam);
  3128. ULONG Response;
  3129. UINT RetVal = 0;
  3130. ((CWinAdminApp*)AfxGetApp())->BeginOutstandingThread();
  3131. MessageParms *pMsgParms = (MessageParms*)pParam;
  3132. // If we are operating on the current selected Item in the tree it's
  3133. // possible that the winstation has disappeared by the time we get here
  3134. // so we should just gracefully cleanup
  3135. if (pMsgParms->bActionOnCurrentSelection)
  3136. {
  3137. if (CWinAdminDoc::gm_CurrentSelType != NODE_WINSTATION)
  3138. {
  3139. goto Cleanup;
  3140. }
  3141. }
  3142. HANDLE hServer = pMsgParms->pWinStation->m_pServer->GetHandle();
  3143. if(!WinStationSendMessage(hServer,
  3144. pMsgParms->pWinStation->m_LogonId,
  3145. pMsgParms->MessageTitle, (wcslen(pMsgParms->MessageTitle)+1)*sizeof(TCHAR),
  3146. pMsgParms->MessageBody, (wcslen(pMsgParms->MessageBody)+1)*sizeof(TCHAR),
  3147. MB_OK, 60, &Response, TRUE ) ) {
  3148. DWORD Error = GetLastError();
  3149. //We need this to know the length of the error message
  3150. //now that StandardErrorMessage requires that
  3151. CString tempErrorMessage;
  3152. tempErrorMessage.LoadString(IDS_ERR_MESSAGE);
  3153. StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
  3154. pMsgParms->pWinStation->m_LogonId, Error, tempErrorMessage.GetLength(),
  3155. 10, IDS_ERR_MESSAGE, pMsgParms->pWinStation->m_LogonId);
  3156. RetVal = 1;
  3157. }
  3158. Cleanup:
  3159. ((CWinAdminApp*)AfxGetApp())->EndOutstandingThread();
  3160. delete pMsgParms;
  3161. return RetVal;
  3162. } // end CWinStation::SendMessage
  3163. /////////////////////////////////////////////////////////////////////////////
  3164. // CWinStation::Disconnect
  3165. //
  3166. UINT CWinStation::Disconnect(LPVOID pParam)
  3167. {
  3168. ASSERT(pParam);
  3169. UINT RetVal = 0;
  3170. HANDLE hServer;
  3171. ((CWinAdminApp*)AfxGetApp())->BeginOutstandingThread();
  3172. DisconnectParms *pDisconnectParms = (DisconnectParms*)pParam;
  3173. // If we are operating on the current selected Item in the tree it's
  3174. // possible that the winstation has disappeared by the time we get here
  3175. // so we should just gracefully cleanup
  3176. if (pDisconnectParms->bActionOnCurrentSelection)
  3177. {
  3178. if (CWinAdminDoc::gm_CurrentSelType != NODE_WINSTATION)
  3179. {
  3180. goto Cleanup;
  3181. }
  3182. }
  3183. hServer = pDisconnectParms->hServer;
  3184. if(!WinStationDisconnect(hServer, pDisconnectParms->ulLogonId, TRUE))
  3185. {
  3186. DWORD Error = GetLastError();
  3187. // We need this to know the length of the error message
  3188. // now that StandardErrorMessage requires that
  3189. CString tempErrorMessage;
  3190. tempErrorMessage.LoadString(IDS_ERR_DISCONNECT);
  3191. StandardErrorMessage(AfxGetAppName(),
  3192. AfxGetMainWnd()->m_hWnd,
  3193. AfxGetInstanceHandle(),
  3194. pDisconnectParms->ulLogonId,
  3195. Error,
  3196. tempErrorMessage.GetLength(),
  3197. 10,
  3198. IDS_ERR_DISCONNECT,
  3199. pDisconnectParms->ulLogonId);
  3200. RetVal = 1;
  3201. }
  3202. Cleanup:
  3203. ((CWinAdminApp*)AfxGetApp())->EndOutstandingThread();
  3204. delete pDisconnectParms;
  3205. return RetVal;
  3206. } // end CWinStation::Disconnect
  3207. /////////////////////////////////////////////////////////////////////////////
  3208. // CWinStation::Reset
  3209. //
  3210. UINT CWinStation::Reset(LPVOID pParam)
  3211. {
  3212. ASSERT(pParam);
  3213. UINT RetVal = 0;
  3214. ((CWinAdminApp*)AfxGetApp())->BeginOutstandingThread();
  3215. ResetParms *pResetParms = (ResetParms*)pParam;
  3216. // If we are operating on the current selected Item in the tree it's
  3217. // possible that the winstation has disappeared by the time we get here
  3218. // so we should just gracefully cleanup
  3219. if (pResetParms->bActionOnCurrentSelection)
  3220. {
  3221. if (CWinAdminDoc::gm_CurrentSelType != NODE_WINSTATION)
  3222. {
  3223. goto Cleanup;
  3224. }
  3225. }
  3226. HANDLE hServer = pResetParms->pWinStation->m_pServer->GetHandle();
  3227. if(!WinStationReset(hServer, pResetParms->pWinStation->m_LogonId, TRUE))
  3228. {
  3229. DWORD Error = GetLastError();
  3230. //We need this to know the length of the error message
  3231. //now that StandardErrorMessage requires that
  3232. CString tempErrorMessage1, tempErrorMessage2;
  3233. tempErrorMessage1.LoadString(IDS_ERR_RESET);
  3234. tempErrorMessage2.LoadString(IDS_ERR_USER_LOGOFF);
  3235. StandardErrorMessage(AfxGetAppName(), AfxGetMainWnd()->m_hWnd, AfxGetInstanceHandle(),
  3236. pResetParms->pWinStation->m_LogonId, Error,
  3237. pResetParms->bReset ? tempErrorMessage1.GetLength() : tempErrorMessage2.GetLength(), 10,
  3238. pResetParms->bReset ? IDS_ERR_RESET : IDS_ERR_USER_LOGOFF, pResetParms->pWinStation->m_LogonId);
  3239. RetVal = 1;
  3240. }
  3241. Cleanup:
  3242. ((CWinAdminApp*)AfxGetApp())->EndOutstandingThread();
  3243. delete pParam;
  3244. return RetVal;
  3245. } // end CWinStation::Reset
  3246. /////////////////////////////////////////////////////////////////////////////
  3247. // CWinStation::QueryAdditionalInformation
  3248. //
  3249. void CWinStation::QueryAdditionalInformation()
  3250. {
  3251. ULONG ReturnLength;
  3252. HANDLE hServer = m_pServer->GetHandle();
  3253. WINSTATIONCLIENT ClientData;
  3254. // Set all the strings to start with a NULL
  3255. m_ClientDir[0] = '\0';
  3256. m_ModemName[0] = '\0';
  3257. m_ClientLicense[0] = '\0';
  3258. m_ClientAddress[0] = '\0';
  3259. m_Colors[0] = '\0';
  3260. // Set all the values to 0
  3261. m_ClientBuildNumber = 0;
  3262. m_ClientProductId = 0;
  3263. m_HostBuffers = 0;
  3264. m_ClientBuffers = 0;
  3265. m_BufferLength = 0;
  3266. m_ClientSerialNumber = 0;
  3267. m_VRes = 0;
  3268. m_HRes = 0;
  3269. SetAdditionalDone();
  3270. if ( WinStationQueryInformation( hServer,
  3271. m_LogonId,
  3272. WinStationClient,
  3273. &ClientData,
  3274. sizeof(WINSTATIONCLIENT),
  3275. &ReturnLength ) ) {
  3276. // Assign string values.
  3277. wcscpy(m_ClientDir, ClientData.ClientDirectory);
  3278. wcscpy(m_ModemName, ClientData.ClientModem);
  3279. wcscpy(m_ClientLicense, ClientData.ClientLicense);
  3280. wcscpy(m_ClientAddress, ClientData.ClientAddress);
  3281. switch ( ClientData.ColorDepth ) {
  3282. case 0x0001:
  3283. wcscpy(m_Colors, TEXT("16"));
  3284. break;
  3285. case 0x0002:
  3286. wcscpy(m_Colors, TEXT("256"));
  3287. break;
  3288. case 0x0004:
  3289. wcscpy(m_Colors, TEXT("64K"));
  3290. break;
  3291. case 0x0008:
  3292. wcscpy(m_Colors, TEXT("16M"));
  3293. break;
  3294. case 0x0010:
  3295. wcscpy(m_Colors, TEXT("32M"));
  3296. break;
  3297. }
  3298. // Assign numeric values.
  3299. m_ClientBuildNumber = ClientData.ClientBuildNumber;
  3300. m_ClientProductId = ClientData.ClientProductId;
  3301. m_HostBuffers = ClientData.OutBufCountHost;
  3302. m_ClientBuffers = ClientData.OutBufCountClient;
  3303. m_BufferLength = ClientData.OutBufLength;
  3304. m_ClientSerialNumber = ClientData.SerialNumber;
  3305. m_HRes = ClientData.HRes;
  3306. m_VRes = ClientData.VRes;
  3307. }
  3308. // If there is an extension DLL loaded, allow it to add it's own info for this WinStation
  3309. LPFNEXWINSTATIONINFOPROC InfoProc = ((CWinAdminApp*)AfxGetApp())->GetExtWinStationInfoProc();
  3310. if(InfoProc) {
  3311. (*InfoProc)(m_pExtensionInfo, m_State);
  3312. }
  3313. LPFNEXGETWINSTATIONMODULESPROC ModuleProc = ((CWinAdminApp*)AfxGetApp())->GetExtGetWinStationModulesProc();
  3314. if(ModuleProc) {
  3315. if(m_pExtModuleInfo) {
  3316. // Get the extension DLL's function to free the module info
  3317. LPFNEXFREEWINSTATIONMODULESPROC FreeModulesProc = ((CWinAdminApp*)AfxGetApp())->GetExtFreeWinStationModulesProc();
  3318. if(FreeModulesProc) {
  3319. (*FreeModulesProc)(m_pExtModuleInfo);
  3320. } else {
  3321. TRACE0("WAExGetWinStationModules exists without WAExFreeWinStationModules\n");
  3322. ASSERT(0);
  3323. }
  3324. }
  3325. m_pExtModuleInfo = (*ModuleProc)(GetExtensionInfo(), &m_NumModules);
  3326. }
  3327. } // end CWinStation::QueryAdditionalInformation
  3328. //////////////////////////////////////////////////////////////////////////////////////////
  3329. //
  3330. // CProcess Member Functions
  3331. //
  3332. //////////////////////////////////////////////////////////////////////////////////////////
  3333. /////////////////////////////////////////////////////////////////////////////
  3334. // CProcess::CProcess
  3335. //
  3336. CProcess::CProcess(ULONG PID,
  3337. ULONG LogonId,
  3338. CServer *pServer,
  3339. PSID pSID,
  3340. CWinStation *pWinStation,
  3341. TCHAR *ImageName)
  3342. {
  3343. ASSERT(pServer);
  3344. DWORD dwImageNameLen;
  3345. m_Flags = PF_CURRENT;
  3346. m_PID = PID;
  3347. m_LogonId = LogonId;
  3348. m_pServer = pServer;
  3349. m_pWinStation = pWinStation;
  3350. m_ImageName = NULL;
  3351. if(PID == 0 && !pSID)
  3352. {
  3353. CString sTemp;
  3354. sTemp.LoadString(IDS_SYSTEM_IDLE_PROCESS);
  3355. // allocate memory for Image Name and copy to member variable
  3356. dwImageNameLen = sTemp.GetLength();
  3357. m_ImageName = (LPTSTR)LocalAlloc(LPTR, (dwImageNameLen + 1) * sizeof(TCHAR));
  3358. if (m_ImageName != NULL)
  3359. {
  3360. _tcscpy(m_ImageName, sTemp);
  3361. }
  3362. SetSystemProcess();
  3363. _tcscpy(m_UserName, TEXT("System"));
  3364. m_SidCrc = 0;
  3365. }
  3366. else
  3367. {
  3368. if(pSID) {
  3369. DWORD SidLength = GetLengthSid(pSID);
  3370. m_SidCrc = CalculateCrc16((PBYTE)pSID, (USHORT)SidLength);
  3371. } else m_SidCrc = 0;
  3372. DetermineProcessUser(pSID);
  3373. // allocate memory for Image Name and copy to member variable
  3374. dwImageNameLen = _tcslen(ImageName);
  3375. m_ImageName = (LPTSTR)LocalAlloc(LPTR, (dwImageNameLen + 1) * sizeof(TCHAR));
  3376. if (m_ImageName != NULL)
  3377. {
  3378. _tcscpy(m_ImageName, ImageName);
  3379. if(QuerySystemProcess()) SetSystemProcess();
  3380. }
  3381. }
  3382. } // end CProcess::CProcess
  3383. TCHAR *SysProcTable[] = {
  3384. TEXT("csrss.exe"),
  3385. TEXT("smss.exe"),
  3386. TEXT("screg.exe"),
  3387. TEXT("lsass.exe"),
  3388. TEXT("spoolss.exe"),
  3389. TEXT("EventLog.exe"),
  3390. TEXT("netdde.exe"),
  3391. TEXT("clipsrv.exe"),
  3392. TEXT("lmsvcs.exe"),
  3393. TEXT("MsgSvc.exe"),
  3394. TEXT("winlogon.exe"),
  3395. TEXT("NETSTRS.EXE"),
  3396. TEXT("nddeagnt.exe"),
  3397. TEXT("wfshell.exe"),
  3398. TEXT("chgcdm.exe"),
  3399. TEXT("userinit.exe"),
  3400. NULL
  3401. };
  3402. /////////////////////////////////////////////////////////////////////////////
  3403. // CProcess::~CProcess
  3404. //
  3405. /////////////////////////////////////////////////////////////////////////////
  3406. CProcess::~CProcess()
  3407. {
  3408. if (m_ImageName != NULL)
  3409. {
  3410. LocalFree(m_ImageName);
  3411. }
  3412. }
  3413. /////////////////////////////////////////////////////////////////////////////
  3414. // CProcess::QuerySystemProcess
  3415. //
  3416. BOOL CProcess::QuerySystemProcess()
  3417. {
  3418. // First: if the user name is 'system' or no image name is present, treat
  3419. // as a 'system' process.
  3420. if(!lstrcmpi(m_UserName, TEXT("system")) ||
  3421. !(*m_ImageName) )
  3422. return TRUE;
  3423. // Last: if the image name is one of the well known 'system' images,
  3424. // treat it as a 'system' process.
  3425. for(int i = 0; SysProcTable[i]; i++)
  3426. if(!lstrcmpi( m_ImageName, SysProcTable[i]))
  3427. return TRUE;
  3428. // Not a 'system' process.
  3429. return FALSE;
  3430. } // end CProcess::QuerySystemProcess
  3431. /////////////////////////////////////////////////////////////////////////////
  3432. // CProcess::DetermineProcessUser
  3433. //
  3434. void CProcess::DetermineProcessUser(PSID pSid)
  3435. {
  3436. CObList *pUserSidList = m_pServer->GetUserSidList();
  3437. // Look for the user Sid in the list
  3438. POSITION pos = pUserSidList->GetHeadPosition();
  3439. while(pos)
  3440. {
  3441. CUserSid *pUserSid = (CUserSid*)pUserSidList->GetNext(pos);
  3442. if(pUserSid->m_SidCrc == m_SidCrc)
  3443. {
  3444. wcscpy(m_UserName, pUserSid->m_UserName);
  3445. return;
  3446. }
  3447. }
  3448. // It wasn't in the list
  3449. // Get the user from the Sid and put it in our list
  3450. GetUserFromSid(pSid, m_UserName, USERNAME_LENGTH);
  3451. if (!lstrcmpi(m_UserName,TEXT("system")))
  3452. {
  3453. wcscpy(m_UserName, TEXT("System")); // to make the UI guys happy
  3454. }
  3455. CUserSid *pUserSid = new CUserSid;
  3456. if(pUserSid == NULL)
  3457. {
  3458. return;
  3459. }
  3460. pUserSid->m_SidCrc = m_SidCrc;
  3461. memset(pUserSid->m_UserName, 0, sizeof(pUserSid->m_UserName));
  3462. lstrcpy(pUserSid->m_UserName, m_UserName);
  3463. pUserSidList->AddTail(pUserSid);
  3464. } // end CProcess::DetermineProcessUser
  3465. /////////////////////////////////////////////////////////////////////////////
  3466. // CProcess::Update
  3467. //
  3468. BOOL CProcess::Update(CProcess *pProcess)
  3469. {
  3470. ASSERT(pProcess);
  3471. BOOL bChanged = FALSE;
  3472. // Check the WinStation
  3473. if(m_pWinStation != pProcess->GetWinStation())
  3474. {
  3475. m_pWinStation = pProcess->GetWinStation();
  3476. bChanged = TRUE;
  3477. }
  3478. else
  3479. {
  3480. if(m_pWinStation->IsChanged())
  3481. {
  3482. bChanged = TRUE;
  3483. }
  3484. }
  3485. if(bChanged) SetChanged();
  3486. return bChanged;
  3487. } // end CProcess::Update
  3488. //////////////////////////////////////////////////////////////////////////////////////////
  3489. //
  3490. // CLicense Member Functions
  3491. //
  3492. //////////////////////////////////////////////////////////////////////////////////////////
  3493. /////////////////////////////////////////////////////////////////////////////
  3494. // CLicense::CLicense
  3495. //
  3496. CLicense::CLicense(CServer *pServer, ExtLicenseInfo *pLicenseInfo)
  3497. {
  3498. ASSERT(pServer);
  3499. ASSERT(pLicenseInfo);
  3500. m_pServer = pServer;
  3501. m_Class = pLicenseInfo->Class;
  3502. m_PoolLicenseCount = pLicenseInfo->PoolLicenseCount;
  3503. m_LicenseCount = pLicenseInfo->LicenseCount;
  3504. m_Flags = pLicenseInfo->Flags;
  3505. wcscpy(m_RegSerialNumber, pLicenseInfo->RegSerialNumber);
  3506. wcscpy(m_LicenseNumber, pLicenseInfo->LicenseNumber);
  3507. wcscpy(m_Description, pLicenseInfo->Description);
  3508. // Figure out the pooling count
  3509. if(m_Flags & ELF_POOLING)
  3510. m_PoolCount = m_PoolLicenseCount;
  3511. else m_PoolCount = 0xFFFFFFFF;
  3512. } // end CLicense::CLicense
  3513. //////////////////////////////////////////////////////////////////////////////////////////
  3514. //
  3515. // CWd Member Functions
  3516. //
  3517. //////////////////////////////////////////////////////////////////////////////////////////
  3518. static CHAR szEncryptionLevels[] = "ExtEncryptionLevels";
  3519. /////////////////////////////////////////////////////////////////////////////
  3520. // CWd::CWd
  3521. //
  3522. CWd::CWd(PWDCONFIG2 pWdConfig, PWDNAME pRegistryName)
  3523. {
  3524. m_pEncryptionLevels = NULL;
  3525. m_NumEncryptionLevels = 0L;
  3526. wcscpy(m_WdName, pWdConfig->Wd.WdName);
  3527. wcscpy(m_RegistryName, pRegistryName);
  3528. // Load the extension DLL for this WD
  3529. m_hExtensionDLL = ::LoadLibrary(pWdConfig->Wd.CfgDLL);
  3530. if(m_hExtensionDLL) {
  3531. // Get the entry points
  3532. m_lpfnExtEncryptionLevels = (LPFNEXTENCRYPTIONLEVELSPROC)::GetProcAddress(m_hExtensionDLL, szEncryptionLevels);
  3533. if(m_lpfnExtEncryptionLevels) {
  3534. m_NumEncryptionLevels = (*m_lpfnExtEncryptionLevels)(NULL, &m_pEncryptionLevels);
  3535. }
  3536. }
  3537. } // end CWd::CWd
  3538. /////////////////////////////////////////////////////////////////////////////
  3539. // CWd::~CWd
  3540. //
  3541. CWd::~CWd()
  3542. {
  3543. if(m_hExtensionDLL) {
  3544. ::FreeLibrary(m_hExtensionDLL);
  3545. }
  3546. } // end CWd::~CWd
  3547. /////////////////////////////////////////////////////////////////////////////
  3548. // CWd::GetEncryptionLevelString
  3549. //
  3550. BOOL CWd::GetEncryptionLevelString(DWORD Value, CString *pString)
  3551. {
  3552. if(!m_NumEncryptionLevels) return FALSE;
  3553. for(LONG i = 0; i < m_NumEncryptionLevels; i++) {
  3554. // Is this the right encryption level
  3555. if(Value == m_pEncryptionLevels[i].RegistryValue) {
  3556. TCHAR estring[128];
  3557. if(::LoadString(m_hExtensionDLL,
  3558. m_pEncryptionLevels[i].StringID, estring, 127)) {
  3559. pString->Format(TEXT("%s"), estring);
  3560. return TRUE;
  3561. }
  3562. return FALSE;
  3563. }
  3564. }
  3565. return FALSE;
  3566. } // end CWd::GetEncryptionLevelString
  3567. //------------------------------------------------
  3568. DWORD Shadow_WarningProc( LPVOID param )
  3569. {
  3570. HINSTANCE hInst = ( HINSTANCE )param;
  3571. OutputDebugString( L"Shadow_WarningProc called\n" );
  3572. DialogBox( hInst , MAKEINTRESOURCE( IDD_DIALOG_SHADOWWARN ) , NULL , ShadowWarn_WndProc );
  3573. OutputDebugString( L"Shadow_WarningProc exiting thread\n" );
  3574. ExitThread( 0 );
  3575. return 0;
  3576. }
  3577. //------------------------------------------------
  3578. INT_PTR CALLBACK ShadowWarn_WndProc( HWND hwnd , UINT msg , WPARAM wp , LPARAM lp )
  3579. {
  3580. switch( msg )
  3581. {
  3582. case WM_INITDIALOG:
  3583. g_hwndShadowWarn = hwnd;
  3584. OutputDebugString( L"WM_INITDIALOG -- in ShadowWarn_WndProc\n" );
  3585. CenterDlg( GetDesktopWindow( ) , hwnd );
  3586. break;
  3587. case WM_CLOSE:
  3588. EndDialog( hwnd , 0 );
  3589. break;
  3590. }
  3591. return FALSE;
  3592. }
  3593. void CenterDlg(HWND hwndToCenterOn , HWND hDlg )
  3594. {
  3595. RECT rc, rcwk, rcToCenterOn;
  3596. SetRect( &rcToCenterOn , 0 , 0 , GetSystemMetrics(SM_CXSCREEN) , GetSystemMetrics( SM_CYSCREEN ) );
  3597. if (hwndToCenterOn != NULL)
  3598. {
  3599. ::GetWindowRect(hwndToCenterOn, &rcToCenterOn);
  3600. }
  3601. ::GetWindowRect( hDlg , &rc);
  3602. UINT uiWidth = rc.right - rc.left;
  3603. UINT uiHeight = rc.bottom - rc.top;
  3604. rc.left = (rcToCenterOn.left + rcToCenterOn.right) / 2 - ( rc.right - rc.left ) / 2;
  3605. rc.top = (rcToCenterOn.top + rcToCenterOn.bottom) / 2 - ( rc.bottom - rc.top ) / 2;
  3606. //ensure the dialog always with the work area
  3607. if(SystemParametersInfo(SPI_GETWORKAREA, 0, &rcwk, 0))
  3608. {
  3609. UINT wkWidth = rcwk.right - rcwk.left;
  3610. UINT wkHeight = rcwk.bottom - rcwk.top;
  3611. if(rc.left + uiWidth > wkWidth) //right cut
  3612. rc.left = wkWidth - uiWidth;
  3613. if(rc.top + uiHeight > wkHeight) //bottom cut
  3614. rc.top = wkHeight - uiHeight;
  3615. if(rc.left < rcwk.left) //left cut
  3616. rc.left += rcwk.left - rc.left;
  3617. if(rc.top < rcwk.top) //top cut
  3618. rc.top += rcwk.top - rc.top;
  3619. }
  3620. ::SetWindowPos( hDlg, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER |
  3621. SWP_NOCOPYBITS | SWP_DRAWFRAME);
  3622. }