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

655 lines
17 KiB

  1. /*******************************************************************************
  2. *
  3. * threads.cpp
  4. *
  5. * implementation of threads classes
  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\winadmin\VCS\threads.cpp $
  13. *
  14. * Rev 1.1 26 Aug 1997 19:15:14 donm
  15. * bug fixes/changes from WinFrame 1.7
  16. *
  17. * Rev 1.0 30 Jul 1997 17:12:44 butchd
  18. * Initial revision.
  19. *
  20. *******************************************************************************/
  21. #include "stdafx.h"
  22. #include "winadmin.h"
  23. #include "threads.h"
  24. #include "led.h"
  25. ////////////////////////////////////////////////////////////////////////////////
  26. // CThread class construction / destruction, implementation
  27. /*******************************************************************************
  28. *
  29. * CThread - CThread constructor
  30. *
  31. * ENTRY:
  32. * EXIT:
  33. *
  34. ******************************************************************************/
  35. CThread::CThread()
  36. {
  37. m_hThread = NULL;
  38. m_dwThreadID = 0;
  39. } // end CThread::CThread
  40. /*******************************************************************************
  41. *
  42. * ~CThread - CThread destructor
  43. *
  44. * ENTRY:
  45. * EXIT:
  46. *
  47. ******************************************************************************/
  48. CThread::~CThread()
  49. {
  50. } // end CThread::~CThread
  51. /*******************************************************************************
  52. *
  53. * operator new - CThread operator override
  54. *
  55. * ENTRY:
  56. * EXIT:
  57. *
  58. ******************************************************************************/
  59. #if 0
  60. void *
  61. CThread::operator new(size_t nSize)
  62. {
  63. return( ::malloc(nSize) );
  64. } // end CThread::operator new
  65. #endif
  66. /*******************************************************************************
  67. *
  68. * operator delete - CThread operator override
  69. *
  70. * ENTRY:
  71. * EXIT:
  72. *
  73. ******************************************************************************/
  74. #if 0
  75. void
  76. CThread::operator delete(void *p)
  77. {
  78. ::free(p);
  79. } // end CThread::operator delete
  80. #endif
  81. ////////////////////////////////////////////////////////////////////////////////
  82. // CThread operations: primary thread
  83. /*******************************************************************************
  84. *
  85. * CreateThread - CThread implementation function
  86. *
  87. * Class wrapper for the Win32 CreateThread API.
  88. *
  89. * ENTRY:
  90. * EXIT:
  91. *
  92. ******************************************************************************/
  93. HANDLE
  94. CThread::CreateThread( DWORD cbStack,
  95. DWORD fdwCreate )
  96. {
  97. /*
  98. * Simple wrapper for Win32 CreateThread API.
  99. */
  100. return( m_hThread = ::CreateThread( NULL, cbStack, ThreadEntryPoint,
  101. (LPVOID)this, fdwCreate, &m_dwThreadID ) );
  102. } // end CThread::CreateThread
  103. ////////////////////////////////////////////////////////////////////////////////
  104. // CThread operations: secondary thread
  105. /*******************************************************************************
  106. *
  107. * ThreadEntryPoint - CThread implementation function
  108. * (SECONDARY THREAD)
  109. *
  110. * ENTRY:
  111. * EXIT:
  112. *
  113. ******************************************************************************/
  114. DWORD __stdcall
  115. CThread::ThreadEntryPoint(LPVOID lpParam)
  116. {
  117. CThread *pThread;
  118. DWORD dwResult;
  119. /*
  120. * (lpParam is actually the 'this' pointer)
  121. */
  122. pThread = (CThread*)lpParam;
  123. VERIFY(pThread != NULL);
  124. /*
  125. * Run the thread.
  126. */
  127. dwResult = pThread->RunThread();
  128. /*
  129. * Return the result.
  130. */
  131. return(dwResult);
  132. } // end CThread::ThreadEntryPoint
  133. ////////////////////////////////////////////////////////////////////////////////
  134. ////////////////////////////////////////////////////////////////////////////////
  135. // CWSStatusThread class construction / destruction, implementation
  136. /*******************************************************************************
  137. *
  138. * CWSStatusThread - CWSStatusThread constructor
  139. *
  140. * ENTRY:
  141. * EXIT:
  142. *
  143. ******************************************************************************/
  144. CWSStatusThread::CWSStatusThread()
  145. {
  146. /*
  147. * Create the semaphore when the CWSStatusThread object is created and
  148. * initialize the m_bExit and m_bResetCounter flags to FALSE.
  149. */
  150. VERIFY( m_hWakeUp = CreateSemaphore( NULL, 0,
  151. MAX_STATUS_SEMAPHORE_COUNT,
  152. NULL ) );
  153. VERIFY( m_hConsumed = CreateSemaphore( NULL, 0,
  154. MAX_STATUS_SEMAPHORE_COUNT,
  155. NULL ) );
  156. m_bExit = FALSE;
  157. } // end CWSStatusThread::CWSStatusThread
  158. /*******************************************************************************
  159. *
  160. * ~CWSStatusThread - CWSStatusThread destructor
  161. *
  162. * ENTRY:
  163. * EXIT:
  164. *
  165. ******************************************************************************/
  166. CWSStatusThread::~CWSStatusThread()
  167. {
  168. /*
  169. * Close the semaphores when the CWSStatusThread object is destroyed.
  170. */
  171. VERIFY( CloseHandle(m_hWakeUp) );
  172. VERIFY( CloseHandle(m_hConsumed) );
  173. } // end CWSStatusThread::~CWSStatusThread
  174. /*******************************************************************************
  175. *
  176. * RunThread - CWSStatusThread secondary thread main function loop
  177. * (SECONDARY THREAD)
  178. *
  179. * ENTRY:
  180. * EXIT:
  181. * (DWORD) exit status for the secondary thread.
  182. *
  183. ******************************************************************************/
  184. DWORD
  185. CWSStatusThread::RunThread()
  186. {
  187. /*
  188. * Query for PD and WinStation information to initialize dialog with.
  189. */
  190. if ( !WSPdQuery() || !WSInfoQuery() ) {
  191. /*
  192. * We can't query the WinStation information: tell the primary
  193. * thread that we've aborted, and exit this thread.
  194. */
  195. PostMessage(m_hDlg, WM_STATUSABORT, 0, 0);
  196. return(1);
  197. } else {
  198. /*
  199. * Tell the primary thread (modeless dialog window) that we've
  200. * got the initial information.
  201. */
  202. PostMessage(m_hDlg, WM_STATUSSTART, 0, 0);
  203. WaitForSingleObject(m_hConsumed, INFINITE);
  204. /*
  205. * Always check for exit request each time we wake up and exit
  206. * the thread if the exit flag is set.
  207. */
  208. if ( m_bExit )
  209. return(0);
  210. }
  211. /*
  212. * Loop till exit requested.
  213. */
  214. for ( ; ; ) {
  215. /*
  216. * Block the thread until time to refresh or we're woken up.
  217. */
  218. WaitForSingleObject( m_hWakeUp, ((CWinAdminApp*)AfxGetApp())->GetStatusRefreshTime());
  219. if ( m_bExit )
  220. return(0);
  221. /*
  222. * Query for WinStation information.
  223. */
  224. if ( !WSInfoQuery() || (m_WSInfo.ConnectState == State_Disconnected) ) {
  225. /*
  226. * Either we can't query the WinStation or it has become
  227. * disconnected: tell the primary thread that we've aborted,
  228. * and exit this thread.
  229. */
  230. PostMessage(m_hDlg, WM_STATUSABORT, 0, 0);
  231. return(1);
  232. } else {
  233. /*
  234. * Tell the dialog that we've got some new query information.
  235. */
  236. PostMessage(m_hDlg, WM_STATUSREADY, 0, 0);
  237. WaitForSingleObject(m_hConsumed, INFINITE);
  238. if ( m_bExit )
  239. return(0);
  240. }
  241. }
  242. } // end CWSStatusThread::RunThread
  243. ////////////////////////////////////////////////////////////////////////////////
  244. // CWSStatusThread operations: primary thread
  245. /*******************************************************************************
  246. *
  247. * SignalWakeUp - CWSStatusThread member function: public operation
  248. *
  249. * Release the m_hWakeUp semaphore to start another status query.
  250. *
  251. * ENTRY:
  252. * EXIT:
  253. *
  254. ******************************************************************************/
  255. void
  256. CWSStatusThread::SignalWakeUp()
  257. {
  258. ReleaseSemaphore(m_hWakeUp, 1, NULL);
  259. } // end CWSStatusThread::SignalWakeUp
  260. /*******************************************************************************
  261. *
  262. * SignalConsumed - CWSStatusThread member function: public operation
  263. *
  264. * Release the m_hConsumed semaphore to allow secondary thread to continue
  265. * running.
  266. *
  267. * ENTRY:
  268. * EXIT:
  269. *
  270. ******************************************************************************/
  271. void
  272. CWSStatusThread::SignalConsumed()
  273. {
  274. ReleaseSemaphore( m_hConsumed, 1, NULL );
  275. } // end CWSStatusThread::SignalConsumed
  276. /*******************************************************************************
  277. *
  278. * ExitThread - CWSStatusThread member function: public operation
  279. *
  280. * Tell the secondary thread to exit and cleanup after.
  281. *
  282. * ENTRY:
  283. * EXIT:
  284. *
  285. ******************************************************************************/
  286. void
  287. CWSStatusThread::ExitThread()
  288. {
  289. DWORD dwReturnCode;
  290. int i;
  291. CWaitCursor Nikki;
  292. /*
  293. * If the thread was not created properly, just delete object and return.
  294. */
  295. if ( !m_hThread ) {
  296. delete this;
  297. return;
  298. }
  299. /*
  300. * Set the m_bExit flag to TRUE and bump both the consumed and wake up
  301. * semaphores to cause RunThread() (the thread's main instructon loop)
  302. * to exit.
  303. */
  304. m_bExit = TRUE;
  305. SignalWakeUp();
  306. SignalConsumed();
  307. /*
  308. * Wait a while for the thread to exit.
  309. */
  310. for ( i = 0, GetExitCodeThread( m_hThread, &dwReturnCode );
  311. (i < MAX_SLEEP_COUNT) && (dwReturnCode == STILL_ACTIVE); i++ ) {
  312. Sleep(100);
  313. GetExitCodeThread( m_hThread, &dwReturnCode );
  314. }
  315. /*
  316. * If the thread has still not exited, terminate it.
  317. */
  318. if ( dwReturnCode == STILL_ACTIVE ) {
  319. TerminateThread( m_hThread, 1 );
  320. #ifdef _DEBUG
  321. // TRACE2( "WSSTATUS: Forced Terminate of thread monitoring LogonID %lu after %u 100msec exit waits.\n",
  322. // m_LogonId, MAX_SLEEP_COUNT );
  323. #endif
  324. }
  325. /*
  326. * Close the thread handle and delete this CWSStatusThread object
  327. */
  328. VERIFY( CloseHandle(m_hThread) );
  329. delete this;
  330. } // end CWSStatusThread::ExitThread
  331. ////////////////////////////////////////////////////////////////////////////////
  332. // CWSStatusThread operations: secondary thread
  333. /*******************************************************************************
  334. *
  335. * WSPdQuery - CWSStatusThread member function: private operation
  336. * (SECONDARY THREAD)
  337. *
  338. * Query the Pd information for the WinStation object referenced by
  339. * the m_LogonId member variable.
  340. *
  341. * ENTRY:
  342. *
  343. * EXIT:
  344. * (BOOL) TRUE if query was sucessful; FALSE otherwise.
  345. *
  346. ******************************************************************************/
  347. BOOL
  348. CWSStatusThread::WSPdQuery()
  349. {
  350. ULONG ReturnLength;
  351. /*
  352. * Query the PD information.
  353. */
  354. memset( &m_PdConfig, 0, sizeof(PDCONFIG) );
  355. if ( !WinStationQueryInformation( m_hServer,
  356. m_LogonId,
  357. WinStationPd,
  358. &m_PdConfig, sizeof(PDCONFIG),
  359. &ReturnLength ) )
  360. goto BadWSQueryInfo;
  361. if(!WinStationQueryInformation(m_hServer,
  362. m_LogonId,
  363. WinStationPd,
  364. &m_PdConfig, sizeof(PDCONFIG),
  365. &ReturnLength ) )
  366. goto BadWSQueryInfo;
  367. return(TRUE);
  368. /*--------------------------------------
  369. * Error clean-up and return...
  370. */
  371. BadWSQueryInfo:
  372. return(FALSE);
  373. } // end CWSStatusThread::WSPdQuery
  374. /*******************************************************************************
  375. *
  376. * WSInfoQuery - CWSStatusThread member function: private operation
  377. * (SECONDARY THREAD)
  378. *
  379. * Query the WinStation information for the WinStation object referenced
  380. * by the m_LogonId member variable.
  381. *
  382. * ENTRY:
  383. *
  384. * EXIT:
  385. * (BOOL) TRUE if query was sucessful; FALSE otherwise.
  386. *
  387. ******************************************************************************/
  388. BOOL
  389. CWSStatusThread::WSInfoQuery()
  390. {
  391. ULONG ReturnLength;
  392. /*
  393. * Query the WinStation information.
  394. */
  395. TRACE0(">>> CWSStatusThread::WSInfoQuery WinStationQueryInformation\n");
  396. if ( !WinStationQueryInformation( m_hServer,
  397. m_LogonId,
  398. WinStationInformation,
  399. &m_WSInfo, sizeof(WINSTATIONINFORMATION),
  400. &ReturnLength ) )
  401. goto BadWSQueryInfo;
  402. TRACE0("<<< CWSStatusThread::WSInfoQuery WinStationQueryInformation (success)\n");
  403. return(TRUE);
  404. /*--------------------------------------
  405. * Error clean-up and return...
  406. */
  407. BadWSQueryInfo:
  408. TRACE0("<<< CWSStatusThread::WSInfoQuery WinStationQueryInformation (error)\n");
  409. return(FALSE);
  410. } // end CWSStatusThread::WSInfoQuery
  411. ///////////////////////////////////////////////////////////////////////////////
  412. // CLed class construction / destruction, implementation
  413. /*******************************************************************************
  414. *
  415. * CLed - CLed constructor
  416. *
  417. * ENTRY:
  418. * hBrush (input)
  419. * Brush to paint window with.
  420. * EXIT:
  421. * (Refer to MFC CStatic::CStatic documentation)
  422. *
  423. ******************************************************************************/
  424. CLed::CLed( HBRUSH hBrush )
  425. : CStatic(),
  426. m_hBrush(hBrush)
  427. {
  428. //{{AFX_DATA_INIT(CLed)
  429. //}}AFX_DATA_INIT
  430. } // end CLed::CLed
  431. ////////////////////////////////////////////////////////////////////////////////
  432. // CLed operations
  433. /*******************************************************************************
  434. *
  435. * Subclass - CLed member function: public operation
  436. *
  437. * Subclass the specified object to our special blip object.
  438. *
  439. * ENTRY:
  440. * pStatic (input)
  441. * Points to CStatic object to subclass.
  442. * EXIT:
  443. *
  444. ******************************************************************************/
  445. void
  446. CLed::Subclass( CStatic *pStatic )
  447. {
  448. SubclassWindow(pStatic->m_hWnd);
  449. } // end CLed::Subclass
  450. /*******************************************************************************
  451. *
  452. * Update - CLed member function: public operation
  453. *
  454. * Update the LED to 'on' or 'off' state.
  455. *
  456. * ENTRY:
  457. * nOn (input)
  458. * nonzero to set 'on' state; zero for 'off' state.
  459. * EXIT:
  460. *
  461. ******************************************************************************/
  462. void
  463. CLed::Update( int nOn )
  464. {
  465. m_bOn = nOn ? TRUE : FALSE;
  466. InvalidateRect(NULL);
  467. UpdateWindow();
  468. } // end CLed::Update
  469. /*******************************************************************************
  470. *
  471. * Toggle - CLed member function: public operation
  472. *
  473. * Toggle the LED's on/off state.
  474. *
  475. * ENTRY:
  476. * EXIT:
  477. *
  478. ******************************************************************************/
  479. void
  480. CLed::Toggle()
  481. {
  482. m_bOn = !m_bOn;
  483. InvalidateRect(NULL);
  484. UpdateWindow();
  485. } // end CLed::Toggle
  486. ////////////////////////////////////////////////////////////////////////////////
  487. // CLed message map
  488. BEGIN_MESSAGE_MAP(CLed, CStatic)
  489. //{{AFX_MSG_MAP(CLed)
  490. ON_WM_PAINT()
  491. //}}AFX_MSG_MAP
  492. END_MESSAGE_MAP()
  493. ////////////////////////////////////////////////////////////////////////////////
  494. // CLed commands
  495. /*******************************************************************************
  496. *
  497. * OnPaint - CLed member function: public operation
  498. *
  499. * Paint the led with its brush for 'on' state.
  500. *
  501. * ENTRY:
  502. * EXIT:
  503. * (Refer to MFC CWnd::OnPaint documentation)
  504. *
  505. ******************************************************************************/
  506. void
  507. CLed::OnPaint()
  508. {
  509. RECT rect;
  510. CPaintDC dc(this);
  511. CBrush brush;
  512. GetClientRect(&rect);
  513. #ifdef USING_3DCONTROLS
  514. (rect.right)--;
  515. (rect.bottom)--;
  516. dc.FrameRect( &rect, brush.FromHandle((HBRUSH)GetStockObject(GRAY_BRUSH)) );
  517. (rect.top)++;
  518. (rect.left)++;
  519. (rect.right)++;
  520. (rect.bottom)++;
  521. dc.FrameRect( &rect, brush.FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)) );
  522. (rect.top)++;
  523. (rect.left)++;
  524. (rect.right) -= 2;
  525. (rect.bottom) -= 2;
  526. #else
  527. dc.FrameRect( &rect, brush.FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH)) );
  528. (rect.top)++;
  529. (rect.left)++;
  530. (rect.right)--;
  531. (rect.bottom)--;
  532. #endif
  533. dc.FillRect( &rect,
  534. brush.FromHandle(
  535. m_bOn ?
  536. m_hBrush :
  537. (HBRUSH)GetStockObject(LTGRAY_BRUSH)) );
  538. } // end CLed::OnPaint
  539. ////////////////////////////////////////////////////////////////////////////////