|
|
/*******************************************************************************
* * threads.cpp * * implementation of threads classes * * copyright notice: Copyright 1997, Citrix Systems Inc. * Copyright (c) 1998 - 1999 Microsoft Corporation * * $Author: donm $ Don Messerli * * $Log: N:\nt\private\utils\citrix\winutils\winadmin\VCS\threads.cpp $ * * Rev 1.1 26 Aug 1997 19:15:14 donm * bug fixes/changes from WinFrame 1.7 * * Rev 1.0 30 Jul 1997 17:12:44 butchd * Initial revision. * *******************************************************************************/
#include "stdafx.h"
#include "winadmin.h"
#include "threads.h"
#include "led.h"
////////////////////////////////////////////////////////////////////////////////
// CThread class construction / destruction, implementation
/*******************************************************************************
* * CThread - CThread constructor * * ENTRY: * EXIT: * ******************************************************************************/
CThread::CThread() { m_hThread = NULL; m_dwThreadID = 0;
} // end CThread::CThread
/*******************************************************************************
* * ~CThread - CThread destructor * * ENTRY: * EXIT: * ******************************************************************************/
CThread::~CThread() { } // end CThread::~CThread
/*******************************************************************************
* * operator new - CThread operator override * * ENTRY: * EXIT: * ******************************************************************************/ #if 0
void * CThread::operator new(size_t nSize) { return( ::malloc(nSize) );
} // end CThread::operator new
#endif
/*******************************************************************************
* * operator delete - CThread operator override * * ENTRY: * EXIT: * ******************************************************************************/ #if 0
void CThread::operator delete(void *p) { ::free(p);
} // end CThread::operator delete
#endif
////////////////////////////////////////////////////////////////////////////////
// CThread operations: primary thread
/*******************************************************************************
* * CreateThread - CThread implementation function * * Class wrapper for the Win32 CreateThread API. * * ENTRY: * EXIT: * ******************************************************************************/
HANDLE CThread::CreateThread( DWORD cbStack, DWORD fdwCreate ) { /*
* Simple wrapper for Win32 CreateThread API. */ return( m_hThread = ::CreateThread( NULL, cbStack, ThreadEntryPoint, (LPVOID)this, fdwCreate, &m_dwThreadID ) );
} // end CThread::CreateThread
////////////////////////////////////////////////////////////////////////////////
// CThread operations: secondary thread
/*******************************************************************************
* * ThreadEntryPoint - CThread implementation function * (SECONDARY THREAD) * * ENTRY: * EXIT: * ******************************************************************************/
DWORD __stdcall CThread::ThreadEntryPoint(LPVOID lpParam) { CThread *pThread; DWORD dwResult;
/*
* (lpParam is actually the 'this' pointer) */ pThread = (CThread*)lpParam; VERIFY(pThread != NULL);
/*
* Run the thread. */ dwResult = pThread->RunThread();
/*
* Return the result. */ return(dwResult);
} // end CThread::ThreadEntryPoint
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// CWSStatusThread class construction / destruction, implementation
/*******************************************************************************
* * CWSStatusThread - CWSStatusThread constructor * * ENTRY: * EXIT: * ******************************************************************************/
CWSStatusThread::CWSStatusThread() { /*
* Create the semaphore when the CWSStatusThread object is created and * initialize the m_bExit and m_bResetCounter flags to FALSE. */ VERIFY( m_hWakeUp = CreateSemaphore( NULL, 0, MAX_STATUS_SEMAPHORE_COUNT, NULL ) ); VERIFY( m_hConsumed = CreateSemaphore( NULL, 0, MAX_STATUS_SEMAPHORE_COUNT, NULL ) ); m_bExit = FALSE;
} // end CWSStatusThread::CWSStatusThread
/*******************************************************************************
* * ~CWSStatusThread - CWSStatusThread destructor * * ENTRY: * EXIT: * ******************************************************************************/
CWSStatusThread::~CWSStatusThread() { /*
* Close the semaphores when the CWSStatusThread object is destroyed. */ VERIFY( CloseHandle(m_hWakeUp) ); VERIFY( CloseHandle(m_hConsumed) );
} // end CWSStatusThread::~CWSStatusThread
/*******************************************************************************
* * RunThread - CWSStatusThread secondary thread main function loop * (SECONDARY THREAD) * * ENTRY: * EXIT: * (DWORD) exit status for the secondary thread. * ******************************************************************************/
DWORD CWSStatusThread::RunThread() { /*
* Query for PD and WinStation information to initialize dialog with. */ if ( !WSPdQuery() || !WSInfoQuery() ) {
/*
* We can't query the WinStation information: tell the primary * thread that we've aborted, and exit this thread. */ PostMessage(m_hDlg, WM_STATUSABORT, 0, 0); return(1);
} else {
/*
* Tell the primary thread (modeless dialog window) that we've * got the initial information. */ PostMessage(m_hDlg, WM_STATUSSTART, 0, 0); WaitForSingleObject(m_hConsumed, INFINITE);
/*
* Always check for exit request each time we wake up and exit * the thread if the exit flag is set. */ if ( m_bExit ) return(0); }
/*
* Loop till exit requested. */ for ( ; ; ) {
/*
* Block the thread until time to refresh or we're woken up. */ WaitForSingleObject( m_hWakeUp, ((CWinAdminApp*)AfxGetApp())->GetStatusRefreshTime()); if ( m_bExit ) return(0);
/*
* Query for WinStation information. */ if ( !WSInfoQuery() || (m_WSInfo.ConnectState == State_Disconnected) ) {
/*
* Either we can't query the WinStation or it has become * disconnected: tell the primary thread that we've aborted, * and exit this thread. */ PostMessage(m_hDlg, WM_STATUSABORT, 0, 0); return(1);
} else {
/*
* Tell the dialog that we've got some new query information. */ PostMessage(m_hDlg, WM_STATUSREADY, 0, 0); WaitForSingleObject(m_hConsumed, INFINITE); if ( m_bExit ) return(0); } }
} // end CWSStatusThread::RunThread
////////////////////////////////////////////////////////////////////////////////
// CWSStatusThread operations: primary thread
/*******************************************************************************
* * SignalWakeUp - CWSStatusThread member function: public operation * * Release the m_hWakeUp semaphore to start another status query. * * ENTRY: * EXIT: * ******************************************************************************/
void CWSStatusThread::SignalWakeUp() { ReleaseSemaphore(m_hWakeUp, 1, NULL);
} // end CWSStatusThread::SignalWakeUp
/*******************************************************************************
* * SignalConsumed - CWSStatusThread member function: public operation * * Release the m_hConsumed semaphore to allow secondary thread to continue * running. * * ENTRY: * EXIT: * ******************************************************************************/
void CWSStatusThread::SignalConsumed() { ReleaseSemaphore( m_hConsumed, 1, NULL );
} // end CWSStatusThread::SignalConsumed
/*******************************************************************************
* * ExitThread - CWSStatusThread member function: public operation * * Tell the secondary thread to exit and cleanup after. * * ENTRY: * EXIT: * ******************************************************************************/
void CWSStatusThread::ExitThread() { DWORD dwReturnCode; int i; CWaitCursor Nikki;
/*
* If the thread was not created properly, just delete object and return. */ if ( !m_hThread ) { delete this; return; }
/*
* Set the m_bExit flag to TRUE and bump both the consumed and wake up * semaphores to cause RunThread() (the thread's main instructon loop) * to exit. */ m_bExit = TRUE; SignalWakeUp(); SignalConsumed();
/*
* Wait a while for the thread to exit. */ for ( i = 0, GetExitCodeThread( m_hThread, &dwReturnCode ); (i < MAX_SLEEP_COUNT) && (dwReturnCode == STILL_ACTIVE); i++ ) {
Sleep(100); GetExitCodeThread( m_hThread, &dwReturnCode ); }
/*
* If the thread has still not exited, terminate it. */ if ( dwReturnCode == STILL_ACTIVE ) {
TerminateThread( m_hThread, 1 );
#ifdef _DEBUG
// TRACE2( "WSSTATUS: Forced Terminate of thread monitoring LogonID %lu after %u 100msec exit waits.\n",
// m_LogonId, MAX_SLEEP_COUNT );
#endif
}
/*
* Close the thread handle and delete this CWSStatusThread object */ VERIFY( CloseHandle(m_hThread) ); delete this;
} // end CWSStatusThread::ExitThread
////////////////////////////////////////////////////////////////////////////////
// CWSStatusThread operations: secondary thread
/*******************************************************************************
* * WSPdQuery - CWSStatusThread member function: private operation * (SECONDARY THREAD) * * Query the Pd information for the WinStation object referenced by * the m_LogonId member variable. * * ENTRY: * * EXIT: * (BOOL) TRUE if query was sucessful; FALSE otherwise. * ******************************************************************************/
BOOL CWSStatusThread::WSPdQuery() { ULONG ReturnLength;
/*
* Query the PD information. */ memset( &m_PdConfig, 0, sizeof(PDCONFIG) ); if ( !WinStationQueryInformation( m_hServer, m_LogonId, WinStationPd, &m_PdConfig, sizeof(PDCONFIG), &ReturnLength ) ) goto BadWSQueryInfo;
if(!WinStationQueryInformation(m_hServer, m_LogonId, WinStationPd, &m_PdConfig, sizeof(PDCONFIG), &ReturnLength ) ) goto BadWSQueryInfo;
return(TRUE);
/*--------------------------------------
* Error clean-up and return... */ BadWSQueryInfo: return(FALSE);
} // end CWSStatusThread::WSPdQuery
/*******************************************************************************
* * WSInfoQuery - CWSStatusThread member function: private operation * (SECONDARY THREAD) * * Query the WinStation information for the WinStation object referenced * by the m_LogonId member variable. * * ENTRY: * * EXIT: * (BOOL) TRUE if query was sucessful; FALSE otherwise. * ******************************************************************************/
BOOL CWSStatusThread::WSInfoQuery() { ULONG ReturnLength;
/*
* Query the WinStation information. */ TRACE0(">>> CWSStatusThread::WSInfoQuery WinStationQueryInformation\n"); if ( !WinStationQueryInformation( m_hServer, m_LogonId, WinStationInformation, &m_WSInfo, sizeof(WINSTATIONINFORMATION), &ReturnLength ) ) goto BadWSQueryInfo; TRACE0("<<< CWSStatusThread::WSInfoQuery WinStationQueryInformation (success)\n");
return(TRUE);
/*--------------------------------------
* Error clean-up and return... */ BadWSQueryInfo: TRACE0("<<< CWSStatusThread::WSInfoQuery WinStationQueryInformation (error)\n"); return(FALSE);
} // end CWSStatusThread::WSInfoQuery
///////////////////////////////////////////////////////////////////////////////
// CLed class construction / destruction, implementation
/*******************************************************************************
* * CLed - CLed constructor * * ENTRY: * hBrush (input) * Brush to paint window with. * EXIT: * (Refer to MFC CStatic::CStatic documentation) * ******************************************************************************/
CLed::CLed( HBRUSH hBrush ) : CStatic(), m_hBrush(hBrush) { //{{AFX_DATA_INIT(CLed)
//}}AFX_DATA_INIT
} // end CLed::CLed
////////////////////////////////////////////////////////////////////////////////
// CLed operations
/*******************************************************************************
* * Subclass - CLed member function: public operation * * Subclass the specified object to our special blip object. * * ENTRY: * pStatic (input) * Points to CStatic object to subclass. * EXIT: * ******************************************************************************/
void CLed::Subclass( CStatic *pStatic ) { SubclassWindow(pStatic->m_hWnd);
} // end CLed::Subclass
/*******************************************************************************
* * Update - CLed member function: public operation * * Update the LED to 'on' or 'off' state. * * ENTRY: * nOn (input) * nonzero to set 'on' state; zero for 'off' state. * EXIT: * ******************************************************************************/
void CLed::Update( int nOn ) { m_bOn = nOn ? TRUE : FALSE; InvalidateRect(NULL); UpdateWindow();
} // end CLed::Update
/*******************************************************************************
* * Toggle - CLed member function: public operation * * Toggle the LED's on/off state. * * ENTRY: * EXIT: * ******************************************************************************/
void CLed::Toggle() { m_bOn = !m_bOn; InvalidateRect(NULL); UpdateWindow();
} // end CLed::Toggle
////////////////////////////////////////////////////////////////////////////////
// CLed message map
BEGIN_MESSAGE_MAP(CLed, CStatic) //{{AFX_MSG_MAP(CLed)
ON_WM_PAINT() //}}AFX_MSG_MAP
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////////////
// CLed commands
/*******************************************************************************
* * OnPaint - CLed member function: public operation * * Paint the led with its brush for 'on' state. * * ENTRY: * EXIT: * (Refer to MFC CWnd::OnPaint documentation) * ******************************************************************************/
void CLed::OnPaint() { RECT rect; CPaintDC dc(this); CBrush brush;
GetClientRect(&rect);
#ifdef USING_3DCONTROLS
(rect.right)--; (rect.bottom)--; dc.FrameRect( &rect, brush.FromHandle((HBRUSH)GetStockObject(GRAY_BRUSH)) );
(rect.top)++; (rect.left)++; (rect.right)++; (rect.bottom)++; dc.FrameRect( &rect, brush.FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)) );
(rect.top)++; (rect.left)++; (rect.right) -= 2; (rect.bottom) -= 2; #else
dc.FrameRect( &rect, brush.FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH)) ); (rect.top)++; (rect.left)++; (rect.right)--; (rect.bottom)--; #endif
dc.FillRect( &rect, brush.FromHandle( m_bOn ? m_hBrush : (HBRUSH)GetStockObject(LTGRAY_BRUSH)) );
} // end CLed::OnPaint
////////////////////////////////////////////////////////////////////////////////
|