// // Driver Verifier UI // Copyright (c) Microsoft Corporation, 1999 // // // // module: SlowDlg.cpp // author: DMihai // created: 11/1/00 // // Description: // #include "stdafx.h" #include "verifier.h" #include "SlowDlg.h" #include "VrfUtil.h" #include "VGlobal.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CSlowProgressDlg dialog CSlowProgressDlg::CSlowProgressDlg( CWnd* pParent /*=NULL*/ ) : CDialog(CSlowProgressDlg::IDD, pParent) { //{{AFX_DATA_INIT(CSlowProgressDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT m_hWorkerThread = NULL; // // Create the event used for killing the worker thread // m_hKillThreadEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); } CSlowProgressDlg::~CSlowProgressDlg() { if( NULL != m_hKillThreadEvent ) { CloseHandle( m_hKillThreadEvent ); } } void CSlowProgressDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CSlowProgressDlg) DDX_Control(pDX, IDC_UNSIGNED_PROGRESS, m_ProgressCtl); DDX_Control(pDX, IDC_UNSIGNED_STATIC, m_CurrentActionStatic); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CSlowProgressDlg, CDialog) //{{AFX_MSG_MAP(CSlowProgressDlg) ON_BN_CLICKED(IDC_UNSIGNED_CANCEL_BUTTON, OnCancelButton) ON_WM_SHOWWINDOW() ON_WM_HELPINFO() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// DWORD WINAPI CSlowProgressDlg::LoadDriverDataWorkerThread( PVOID p ) { CSlowProgressDlg *pThis; pThis = (CSlowProgressDlg *)p; // // Cannot ASSERT_VALID for a CWnd from a thread that didn't create the window in MFC... // ASSERT( NULL != pThis ); // // Load all the drivers information (name, version, etc.) // if we haven't don that already // g_NewVerifierSettings.m_DriversSet.LoadAllDriversData( pThis->m_hKillThreadEvent, pThis->m_ProgressCtl ); // // Done - hide the "slow progress" dialog and press the wizard "next" button // pThis->ShowWindow( SW_HIDE ); if( g_NewVerifierSettings.m_DriversSet.m_bDriverDataInitialized ) { AfxGetMainWnd()->PostMessage(PSM_PRESSBUTTON, (WPARAM)PSBTN_NEXT, 0) ; } return 0; } ///////////////////////////////////////////////////////////////////////////// DWORD WINAPI CSlowProgressDlg::SearchUnsignedDriversWorkerThread( PVOID p ) { CSlowProgressDlg *pThis; pThis = (CSlowProgressDlg *)p; // // Cannot ASSERT_VALID for a CWnd from a thread that didn't create the window in MFC... // ASSERT( NULL != pThis ); // // Find out the unsigned drivers if we didn't do that already // g_NewVerifierSettings.m_DriversSet.FindUnsignedDrivers( pThis->m_hKillThreadEvent, pThis->m_ProgressCtl ); // // Done - hide the "slow progress" dialog and press the wizard "next" button // pThis->ShowWindow( SW_HIDE ); if( g_NewVerifierSettings.m_DriversSet.m_bUnsignedDriverDataInitialized ) { AfxGetMainWnd()->PostMessage(PSM_PRESSBUTTON, (WPARAM)PSBTN_NEXT, 0) ; } return 0; } ///////////////////////////////////////////////////////////////////////////// BOOL CSlowProgressDlg::StartWorkerThread( LPTHREAD_START_ROUTINE pThreadStart, ULONG uMessageResourceId ) { DWORD dwThreadId; CString strWorkMessage; // // Load a description of the current "work item" // and show it to the user // VERIFY( strWorkMessage.LoadString( uMessageResourceId ) ); m_CurrentActionStatic.SetWindowText( strWorkMessage ); m_CurrentActionStatic.RedrawWindow(); // // Kill a possible currently running worker thread // KillWorkerThread(); ASSERT( NULL == m_hWorkerThread ); // // Make sure the "kill thread" event is not signaled // if( NULL != m_hKillThreadEvent ) { ResetEvent( m_hKillThreadEvent ); } // // Create the new worker thread // m_hWorkerThread = CreateThread( NULL, 0, pThreadStart, this, 0, &dwThreadId ); if( NULL == m_hWorkerThread ) { // // Could not create the worker thread - bail out // VrfErrorResourceFormat( IDS_NOT_ENOUGH_MEMORY ); PostMessage( WM_COMMAND, IDC_UNSIGNED_CANCEL_BUTTON ); return FALSE; } return TRUE; } ///////////////////////////////////////////////////////////////////////////// VOID CSlowProgressDlg::KillWorkerThread() { DWORD dwWaitResult; MSG msg; if( NULL != m_hWorkerThread ) { if( NULL != m_hKillThreadEvent ) { // // Ask the worker thread to die asap // SetEvent( m_hKillThreadEvent ); } // // Wait forever for a decent death from the worker thread. // // We cannot TerminateThread on our worker thread because // it could be killed while holding locks (e.g. the heap lock) // and that would deadlock our whole process. // while( m_hWorkerThread != NULL ) { dwWaitResult = MsgWaitForMultipleObjects( 1, &m_hWorkerThread, FALSE, INFINITE, QS_ALLINPUT ); ASSERT( NULL != WAIT_FAILED ); if( WAIT_OBJECT_0 != dwWaitResult ) { // // Our thread didn't exit but we have some messages to dispatch. // while( PeekMessage( &msg, NULL, NULL, NULL, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } // // During the DispatchMessage above we could process another // click of the Cancel button or the Back button of the wizard. // The KillWorkerThread recursive call will wait until the worker // thread dies then will sets m_hWorkerThread to NULL. // So we need to check for m_hWorkerThread != NULL before each new // MsgWaitForMultipleObjects. // } else { // // The worker thread finished execution. // break; } } if( m_hWorkerThread != NULL ) { // // Close the thread handle // CloseHandle( m_hWorkerThread ); m_hWorkerThread = NULL; } } } ///////////////////////////////////////////////////////////////////////////// // CSlowProgressDlg message handlers void CSlowProgressDlg::OnCancelButton() { KillWorkerThread(); ShowWindow( SW_HIDE ); } ///////////////////////////////////////////////////////////////////////////// void CSlowProgressDlg::OnShowWindow(BOOL bShow, UINT nStatus) { CDialog::OnShowWindow(bShow, nStatus); if( TRUE == bShow ) { CenterWindow(); } } ///////////////////////////////////////////////////////////////////////////// BOOL CSlowProgressDlg::OnHelpInfo(HELPINFO* pHelpInfo) { return TRUE; }