windows-nt/Source/XPSP1/NT/sdktools/verifier/slowdlg.cpp
2020-09-26 16:20:57 +08:00

313 lines
7.6 KiB
C++

//
// 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;
}