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.
 
 
 
 
 
 

1070 lines
25 KiB

//
// Driver Verifier UI
// Copyright (c) Microsoft Corporation, 1999
//
//
//
// module: SDrvPage.cpp
// author: DMihai
// created: 11/1/00
//
// Description:
//
#include "stdafx.h"
#include <Cderr.h>
#include "verifier.h"
#include "SDrvPage.h"
#include "VrfUtil.h"
#include "VGlobal.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// Help IDs
//
static DWORD MyHelpIds[] =
{
IDC_SELDRV_LIST, IDH_DV_SelectDriversToVerify,
IDC_SELDRV_ADD_BUTTON, IDH_DV_Addbut_UnloadedDrivers,
0, 0
};
/////////////////////////////////////////////////////////////////////////////
// CSelectDriversPage property page
IMPLEMENT_DYNCREATE(CSelectDriversPage, CVerifierPropertyPage)
CSelectDriversPage::CSelectDriversPage()
: CVerifierPropertyPage(CSelectDriversPage::IDD)
{
//{{AFX_DATA_INIT(CSelectDriversPage)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_pParentSheet = NULL;
m_nSortColumnIndex = 1;
m_bAscendSortVerified = FALSE;
m_bAscendSortDrvName = FALSE;
m_bAscendSortProvName = FALSE;
m_bAscendSortVersion = FALSE;
}
CSelectDriversPage::~CSelectDriversPage()
{
}
void CSelectDriversPage::DoDataExchange(CDataExchange* pDX)
{
CVerifierPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSelectDriversPage)
DDX_Control(pDX, IDC_SELDRV_NEXT_DESCR_STATIC, m_NextDescription);
DDX_Control(pDX, IDC_SELDRV_LIST, m_DriversList);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CSelectDriversPage, CVerifierPropertyPage)
//{{AFX_MSG_MAP(CSelectDriversPage)
ON_BN_CLICKED(IDC_SELDRV_ADD_BUTTON, OnAddButton)
ON_NOTIFY(LVN_COLUMNCLICK, IDC_SELDRV_LIST, OnColumnclickSeldrvList)
ON_WM_CONTEXTMENU()
ON_MESSAGE( WM_HELP, OnHelp )
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
VOID CSelectDriversPage::SetupListHeader()
{
CString strTitle;
CRect rectWnd;
LVCOLUMN lvColumn;
//
// The list's rectangle
//
m_DriversList.GetClientRect( &rectWnd );
ZeroMemory( &lvColumn,
sizeof( lvColumn ) );
lvColumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
//
// Column 0
//
VERIFY( strTitle.LoadString( IDS_VERIFICATION_STATUS ) );
lvColumn.iSubItem = 0;
lvColumn.cx = (int)( rectWnd.Width() * 0.08 );
lvColumn.pszText = strTitle.GetBuffer( strTitle.GetLength() + 1 );
if (NULL != lvColumn.pszText)
{
VERIFY( m_DriversList.InsertColumn( 0, &lvColumn ) != -1 );
strTitle.ReleaseBuffer();
}
else
{
lvColumn.pszText = g_szVoidText;
VERIFY( m_DriversList.InsertColumn( 0, &lvColumn ) != -1 );
}
//
// Column 1
//
VERIFY( strTitle.LoadString( IDS_DRIVERS ) );
lvColumn.iSubItem = 1;
lvColumn.cx = (int)( rectWnd.Width() * 0.20 );
lvColumn.pszText = strTitle.GetBuffer( strTitle.GetLength() + 1 );
if (NULL != lvColumn.pszText)
{
VERIFY( m_DriversList.InsertColumn( 1, &lvColumn ) != -1 );
strTitle.ReleaseBuffer();
}
else
{
lvColumn.pszText = g_szVoidText;
VERIFY( m_DriversList.InsertColumn( 1, &lvColumn ) != -1 );
}
//
// Column 2
//
VERIFY( strTitle.LoadString( IDS_PROVIDER ) );
lvColumn.iSubItem = 2;
lvColumn.cx = (int)( rectWnd.Width() * 0.47 );
lvColumn.pszText = strTitle.GetBuffer( strTitle.GetLength() + 1 );
if (NULL != lvColumn.pszText)
{
VERIFY( m_DriversList.InsertColumn( 2, &lvColumn ) != -1 );
strTitle.ReleaseBuffer();
}
else
{
lvColumn.pszText = g_szVoidText;
VERIFY( m_DriversList.InsertColumn( 2, &lvColumn ) != -1 );
}
//
// Column 3
//
VERIFY( strTitle.LoadString( IDS_VERSION ) );
lvColumn.iSubItem = 3;
lvColumn.cx = (int)( rectWnd.Width() * 0.22 );
lvColumn.pszText = strTitle.GetBuffer( strTitle.GetLength() + 1 );
if (NULL != lvColumn.pszText)
{
VERIFY( m_DriversList.InsertColumn( 3, &lvColumn ) != -1 );
strTitle.ReleaseBuffer();
}
else
{
VERIFY( m_DriversList.InsertColumn( 3, &lvColumn ) != -1 );
lvColumn.pszText = g_szVoidText;
}
}
/////////////////////////////////////////////////////////////////////////////
VOID CSelectDriversPage::FillTheList()
{
INT_PTR nDriversNo;
INT_PTR nCrtDriverIndex;
CDriverData *pCrtDrvData;
const CDriverDataArray &DrvDataArray = g_NewVerifierSettings.m_DriversSet.m_aDriverData;
m_DriversList.DeleteAllItems();
//
// Parse the driver data array
//
nDriversNo = DrvDataArray.GetSize();
for( nCrtDriverIndex = 0; nCrtDriverIndex < nDriversNo; nCrtDriverIndex += 1)
{
pCrtDrvData = DrvDataArray.GetAt( nCrtDriverIndex );
ASSERT_VALID( pCrtDrvData );
AddListItem( nCrtDriverIndex,
pCrtDrvData );
}
}
/////////////////////////////////////////////////////////////////////////////
INT CSelectDriversPage::AddListItem( INT_PTR nIndexInArray, CDriverData *pCrtDrvData )
{
INT nActualIndex;
LVITEM lvItem;
ASSERT_VALID( pCrtDrvData );
nActualIndex = -1;
ZeroMemory( &lvItem, sizeof( lvItem ) );
//
// LVITEM's member pszText is not a const pointer
// so we need to GetBuffer here :-(
//
//
// Sub-item 0 - verification status - empty text and a checkbox
//
lvItem.pszText = g_szVoidText;
lvItem.mask = LVIF_TEXT | LVIF_PARAM;
lvItem.lParam = nIndexInArray;
lvItem.iItem = m_DriversList.GetItemCount();
nActualIndex = m_DriversList.InsertItem( &lvItem );
if( nActualIndex < 0 )
{
//
// Could not add an item in the list - give up
//
goto Done;
}
m_DriversList.SetCheck( nActualIndex, FALSE );
//
// Sub-item 1 - driver name
//
lvItem.pszText = pCrtDrvData->m_strName.GetBuffer( pCrtDrvData->m_strName.GetLength() + 1 );
if( NULL == lvItem.pszText )
{
goto Done;
}
lvItem.mask = LVIF_TEXT;
lvItem.iItem = nActualIndex;
lvItem.iSubItem = 1;
VERIFY( m_DriversList.SetItem( &lvItem ) );
pCrtDrvData->m_strName.ReleaseBuffer();
//
// Sub-item 2 - provider
//
lvItem.pszText = pCrtDrvData->m_strCompanyName.GetBuffer(
pCrtDrvData->m_strCompanyName.GetLength() + 1 );
if( NULL == lvItem.pszText )
{
goto Done;
}
lvItem.mask = LVIF_TEXT;
lvItem.iItem = nActualIndex;
lvItem.iSubItem = 2;
VERIFY( m_DriversList.SetItem( &lvItem ) );
pCrtDrvData->m_strCompanyName.ReleaseBuffer();
//
// Sub-item 3 - version
//
lvItem.pszText = pCrtDrvData->m_strFileVersion.GetBuffer(
pCrtDrvData->m_strFileVersion.GetLength() + 1 );
if( NULL == lvItem.pszText )
{
goto Done;
}
lvItem.mask = LVIF_TEXT;
lvItem.iItem = nActualIndex;
lvItem.iSubItem = 3;
VERIFY( m_DriversList.SetItem( &lvItem ) );
pCrtDrvData->m_strFileVersion.ReleaseBuffer();
Done:
//
// All done
//
return nActualIndex;
}
/////////////////////////////////////////////////////////////////////////////
BOOL CSelectDriversPage::GetNewVerifiedDriversList()
{
INT nListItemCount;
INT nCrtListItem;
INT_PTR nCrtDriversArrayIndex;
BOOL bVerified;
CDriverData *pCrtDrvData;
const CDriverDataArray &DrvDataArray = g_NewVerifierSettings.m_DriversSet.m_aDriverData;
CDriverData::VerifyDriverTypeEnum VerifyStatus;
nListItemCount = m_DriversList.GetItemCount();
for( nCrtListItem = 0; nCrtListItem < nListItemCount; nCrtListItem += 1 )
{
//
// Verification status for the current list item
//
bVerified = m_DriversList.GetCheck( nCrtListItem );
if( bVerified )
{
VerifyStatus = CDriverData::VerifyDriverYes;
}
else
{
VerifyStatus = CDriverData::VerifyDriverNo;
}
//
// Set the right verify state in our driver array
//
nCrtDriversArrayIndex = m_DriversList.GetItemData( nCrtListItem );
pCrtDrvData = DrvDataArray.GetAt( nCrtDriversArrayIndex );
ASSERT_VALID( pCrtDrvData );
pCrtDrvData->m_VerifyDriverStatus = VerifyStatus;
}
return TRUE;
}
/////////////////////////////////////////////////////////////
VOID CSelectDriversPage::SortTheList()
{
if( 0 != m_nSortColumnIndex )
{
//
// Sort by driver name, provider or version
//
m_DriversList.SortItems( StringCmpFunc, (LPARAM)this );
}
else
{
//
// Sort by verified status
//
m_DriversList.SortItems( CheckedStatusCmpFunc, (LPARAM)this );
}
}
/////////////////////////////////////////////////////////////
int CALLBACK CSelectDriversPage::StringCmpFunc( LPARAM lParam1,
LPARAM lParam2,
LPARAM lParamSort)
{
int nCmpRez = 0;
BOOL bSuccess;
CString strName1;
CString strName2;
CSelectDriversPage *pThis = (CSelectDriversPage *)lParamSort;
ASSERT_VALID( pThis );
ASSERT( 0 != pThis->m_nSortColumnIndex );
//
// Get the first name
//
bSuccess = pThis->GetColumnStrValue( lParam1,
strName1 );
if( FALSE == bSuccess )
{
goto Done;
}
//
// Get the second name
//
bSuccess = pThis->GetColumnStrValue( lParam2,
strName2 );
if( FALSE == bSuccess )
{
goto Done;
}
//
// Compare the names
//
nCmpRez = strName1.CompareNoCase( strName2 );
switch( pThis->m_nSortColumnIndex )
{
case 1:
//
// Sort by driver name
//
if( FALSE != pThis->m_bAscendSortDrvName )
{
nCmpRez *= -1;
}
break;
case 2:
//
// Sort by provider name
//
if( FALSE != pThis->m_bAscendSortProvName )
{
nCmpRez *= -1;
}
break;
case 3:
//
// Sort by version
//
if( FALSE != pThis->m_bAscendSortVersion )
{
nCmpRez *= -1;
}
break;
default:
//
// Oops - how did we get here ?!?
//
ASSERT( FALSE );
break;
}
Done:
return nCmpRez;
}
/////////////////////////////////////////////////////////////
int CALLBACK CSelectDriversPage::CheckedStatusCmpFunc( LPARAM lParam1,
LPARAM lParam2,
LPARAM lParamSort)
{
int nCmpRez = 0;
INT nItemIndex;
BOOL bVerified1;
BOOL bVerified2;
LVFINDINFO FindInfo;
CSelectDriversPage *pThis = (CSelectDriversPage *)lParamSort;
ASSERT_VALID( pThis );
ASSERT( 0 == pThis->m_nSortColumnIndex );
//
// Find the first item
//
ZeroMemory( &FindInfo, sizeof( FindInfo ) );
FindInfo.flags = LVFI_PARAM;
FindInfo.lParam = lParam1;
nItemIndex = pThis->m_DriversList.FindItem( &FindInfo );
if( nItemIndex < 0 )
{
ASSERT( FALSE );
goto Done;
}
bVerified1 = pThis->m_DriversList.GetCheck( nItemIndex );
//
// Find the second item
//
FindInfo.flags = LVFI_PARAM;
FindInfo.lParam = lParam2;
nItemIndex = pThis->m_DriversList.FindItem( &FindInfo );
if( nItemIndex < 0 )
{
ASSERT( FALSE );
goto Done;
}
bVerified2 = pThis->m_DriversList.GetCheck( nItemIndex );
//
// Compare them
//
if( bVerified1 != bVerified2 )
{
if( FALSE != bVerified1 )
{
nCmpRez = 1;
}
else
{
nCmpRez = -1;
}
if( FALSE != pThis->m_bAscendSortVerified )
{
nCmpRez *= -1;
}
}
Done:
return nCmpRez;
}
/////////////////////////////////////////////////////////////
BOOL CSelectDriversPage::GetColumnStrValue( LPARAM lItemData,
CString &strName )
{
CDriverData *pCrtDrvData;
pCrtDrvData = g_NewVerifierSettings.m_DriversSet.m_aDriverData.GetAt( (INT_PTR) lItemData );
ASSERT_VALID( pCrtDrvData );
switch( m_nSortColumnIndex )
{
case 1:
//
// Sort by driver name
//
strName = pCrtDrvData->m_strName;
break;
case 2:
//
// Sort by provider name
//
strName = pCrtDrvData->m_strCompanyName;
break;
case 3:
//
// Sort by version
//
strName = pCrtDrvData->m_strFileVersion;
break;
default:
//
// Oops - how did we get here ?!?
//
ASSERT( FALSE );
break;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
BOOL CSelectDriversPage::OnSetActive()
{
//
// The wizard has at least one more step (display the summarry)
//
if( (FALSE == g_bShowDiskPropertyPage) &&
(FALSE == g_NewVerifierSettings.m_aDiskData.VerifyAnyDisk()) )
{
//
// Disk verifier is disabled.
//
m_pParentSheet->SetWizardButtons( PSWIZB_BACK |
PSWIZB_FINISH );
VrfSetWindowText( m_NextDescription, IDS_SELDRV_PAGE_NEXT_DESCR_FINISH );
}
else
{
//
// Disk verifier is enabled.
//
m_pParentSheet->SetWizardButtons( PSWIZB_BACK |
PSWIZB_NEXT );
VrfSetWindowText( m_NextDescription, IDS_SELDRV_PAGE_NEXT_DESCR_NEXT );
}
return CVerifierPropertyPage::OnSetActive();
}
/////////////////////////////////////////////////////////////////////////////
// CSelectDriversPage message handlers
BOOL CSelectDriversPage::OnInitDialog()
{
CVerifierPropertyPage::OnInitDialog();
//
// setup the list
//
m_DriversList.SetExtendedStyle(
LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES | m_DriversList.GetExtendedStyle() );
SetupListHeader();
FillTheList();
SortTheList();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
/////////////////////////////////////////////////////////////////////////////
BOOL CSelectDriversPage::OnWizardFinish()
{
BOOL bExitTheApp;
bExitTheApp = FALSE;
if( GetNewVerifiedDriversList() )
{
if( FALSE == g_NewVerifierSettings.m_DriversSet.ShouldVerifySomeDrivers() )
{
VrfErrorResourceFormat( IDS_SELECT_AT_LEAST_ONE_DRIVER );
goto Done;
}
g_NewVerifierSettings.SaveToRegistry();
//
// Exit the app
//
bExitTheApp = CVerifierPropertyPage::OnWizardFinish();
}
Done:
return bExitTheApp;
}
/////////////////////////////////////////////////////////////////////////////
LRESULT CSelectDriversPage::OnWizardNext()
{
LRESULT lNextPageId;
lNextPageId = -1;
//
// We can get here only if the disk integrity checking is enabled.
//
ASSERT( FALSE != g_bShowDiskPropertyPage ||
FALSE != g_NewVerifierSettings.m_aDiskData.VerifyAnyDisk() );
if( GetNewVerifiedDriversList() )
{
if( FALSE == g_NewVerifierSettings.m_DriversSet.ShouldVerifySomeDrivers() )
{
VrfErrorResourceFormat( IDS_SELECT_AT_LEAST_ONE_DRIVER );
goto Done;
}
lNextPageId = IDD_DISK_LIST_PAGE;
GoingToNextPageNotify( lNextPageId );
}
Done:
return lNextPageId;
}
/////////////////////////////////////////////////////////////////////////////
#define VRF_MAX_CHARS_FOR_OPEN 4096
void CSelectDriversPage::OnAddButton()
{
POSITION pos;
DWORD dwRetValue;
DWORD dwOldMaxFileName = 0;
DWORD dwErrorCode;
INT nFileNameStartIndex;
INT nNewListItemIndex;
INT_PTR nResult;
INT_PTR nNewDriverDataIndex;
CDriverData *pNewDrvData;
TCHAR szDriversDir[ _MAX_PATH ];
TCHAR szAppTitle[ _MAX_PATH ];
TCHAR *szFilesBuffer = NULL;
TCHAR *szOldFilesBuffer = NULL;
CString strPathName;
CString strFileName;
CFileDialog fileDlg(
TRUE, // open file
_T( "sys" ), // default extension
NULL, // no initial file name
OFN_ALLOWMULTISELECT | // multiple selection
OFN_HIDEREADONLY | // hide the "open read-only" checkbox
OFN_NONETWORKBUTTON | // no network button
OFN_NOTESTFILECREATE | // don't test for write protection, a full disk, etc.
OFN_SHAREAWARE, // don't check the existance of file with OpenFile
_T( "Drivers (*.sys)|*.sys||" ) ); // only one filter
//
// check the max length for the returned string
//
if( fileDlg.m_ofn.nMaxFile < VRF_MAX_CHARS_FOR_OPEN )
{
//
// allocate a new buffer for the file names
//
szFilesBuffer = new TCHAR[ VRF_MAX_CHARS_FOR_OPEN ];
if (NULL == szFilesBuffer)
{
VrfErrorResourceFormat( IDS_NOT_ENOUGH_MEMORY );
goto Done;
}
szFilesBuffer[ 0 ] = (TCHAR)0;
if( szFilesBuffer != NULL )
{
//
// Save the old buffer address and length
//
dwOldMaxFileName = fileDlg.m_ofn.nMaxFile;
szOldFilesBuffer = fileDlg.m_ofn.lpstrFile;
//
// Set the new buffer address and length
//
fileDlg.m_ofn.lpstrFile = szFilesBuffer;
fileDlg.m_ofn.nMaxFile = VRF_MAX_CHARS_FOR_OPEN;
}
}
//
// Dialog title
//
if( VrfLoadString(
IDS_APPTITLE,
szAppTitle,
ARRAY_LENGTH( szAppTitle ) ) )
{
fileDlg.m_ofn.lpstrTitle = szAppTitle;
}
//
// We change directory first time we try this to %windir%\system32\drivers
//
dwRetValue = ExpandEnvironmentStrings(
_T( "%windir%\\system32\\drivers" ),
szDriversDir,
ARRAY_LENGTH( szDriversDir ) );
if( dwRetValue > 0 && dwRetValue <= ARRAY_LENGTH( szDriversDir ) )
{
fileDlg.m_ofn.lpstrInitialDir = szDriversDir;
}
//
// Show the file selection dialog
//
nResult = fileDlg.DoModal();
switch( nResult )
{
case IDOK:
break;
case IDCANCEL:
goto cleanup;
default:
dwErrorCode = CommDlgExtendedError();
if( dwErrorCode == FNERR_BUFFERTOOSMALL )
{
VrfErrorResourceFormat(
IDS_TOO_MANY_FILES_SELECTED );
}
else
{
VrfErrorResourceFormat(
IDS_CANNOT_OPEN_FILES,
dwErrorCode );
}
goto cleanup;
}
//
// Parse all the selected files and try to enable them for verification
//
pos = fileDlg.GetStartPosition();
while( pos != NULL )
{
//
// Get the full path for the next file
//
strPathName = fileDlg.GetNextPathName( pos );
//
// Split only the file name, without the directory
//
nFileNameStartIndex = strPathName.ReverseFind( _T( '\\' ) );
if( nFileNameStartIndex < 0 )
{
//
// This shoudn't happen but you never know :-)
//
nFileNameStartIndex = 0;
}
else
{
//
// skip the backslash
//
nFileNameStartIndex += 1;
}
strFileName = strPathName.Right( strPathName.GetLength() - nFileNameStartIndex );
//
// Try to add this driver to our global driver list
//
if( g_NewVerifierSettings.m_DriversSet.IsDriverNameInList( strFileName ) )
{
VrfErrorResourceFormat( IDS_DRIVER_IS_ALREADY_IN_LIST,
(LPCTSTR) strFileName );
}
else
{
nNewDriverDataIndex = g_NewVerifierSettings.m_DriversSet.AddNewDriverData( strFileName );
if( nNewDriverDataIndex >= 0 )
{
//
// Force refreshing the unsigned driver data
//
g_NewVerifierSettings.m_DriversSet.m_bUnsignedDriverDataInitialized = FALSE;
//
// Add a new item to our list, for the new driver
//
pNewDrvData = g_NewVerifierSettings.m_DriversSet.m_aDriverData.GetAt( nNewDriverDataIndex );
ASSERT_VALID( pNewDrvData );
nNewListItemIndex = AddListItem( nNewDriverDataIndex,
pNewDrvData );
if( nNewListItemIndex >= 0 )
{
m_DriversList.EnsureVisible( nNewListItemIndex, TRUE );
}
}
}
}
cleanup:
if( szFilesBuffer != NULL )
{
fileDlg.m_ofn.nMaxFile = dwOldMaxFileName;
fileDlg.m_ofn.lpstrFile = szOldFilesBuffer;
delete [] szFilesBuffer;
}
Done:
NOTHING;
}
/////////////////////////////////////////////////////////////////////////////
void CSelectDriversPage::OnColumnclickSeldrvList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
switch( pNMListView->iSubItem )
{
case 0:
//
// Clicked on the "verified" column
//
if( m_nSortColumnIndex == pNMListView->iSubItem )
{
//
// Change the current ascend/descend order for this column
//
m_bAscendSortVerified = !m_bAscendSortVerified;
}
break;
case 1:
//
// Clicked on the driver name column
//
if( m_nSortColumnIndex == pNMListView->iSubItem )
{
//
// Change the current ascend/descend order for this column
//
m_bAscendSortDrvName = !m_bAscendSortDrvName;
}
break;
case 2:
//
// Clicked on the provider column
//
if( m_nSortColumnIndex == pNMListView->iSubItem )
{
//
// Change the current ascend/descend order for this column
//
m_bAscendSortProvName = !m_bAscendSortProvName;
}
break;
case 3:
//
// Clicked on the version column
//
if( m_nSortColumnIndex == pNMListView->iSubItem )
{
//
// Change the current ascend/descend order for this column
//
m_bAscendSortVersion = !m_bAscendSortVersion;
}
break;
default:
//
// Oops - how did we get here ?!?
//
ASSERT( FALSE );
goto Done;
}
m_nSortColumnIndex = pNMListView->iSubItem;
SortTheList();
Done:
*pResult = 0;
}
/////////////////////////////////////////////////////////////
LONG CSelectDriversPage::OnHelp( WPARAM wParam, LPARAM lParam )
{
LONG lResult = 0;
LPHELPINFO lpHelpInfo = (LPHELPINFO)lParam;
::WinHelp(
(HWND) lpHelpInfo->hItemHandle,
g_szVerifierHelpFile,
HELP_WM_HELP,
(DWORD_PTR) MyHelpIds );
return lResult;
}
/////////////////////////////////////////////////////////////////////////////
void CSelectDriversPage::OnContextMenu(CWnd* pWnd, CPoint point)
{
::WinHelp(
pWnd->m_hWnd,
g_szVerifierHelpFile,
HELP_CONTEXTMENU,
(DWORD_PTR) MyHelpIds );
}