Source code of Windows XP (NT5)
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.

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