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.
1105 lines
27 KiB
1105 lines
27 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1996 - 1998
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
archlv.hxx
|
|
|
|
Abstract:
|
|
|
|
Driver Architecture List View
|
|
|
|
Author:
|
|
|
|
Steve Kiraly (SteveKi) 19-Nov-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "psetup.hxx"
|
|
#include "drvsetup.hxx"
|
|
#include "drvver.hxx"
|
|
#include "archlv.hxx"
|
|
|
|
/********************************************************************
|
|
|
|
Arch List - static data.
|
|
|
|
********************************************************************/
|
|
|
|
static TArchLV::ArchVerEncode aArchVerEncode[] =
|
|
{
|
|
{IDS_ARCH_ITANIUM, IDS_VERSION_XP_NET, L"Windows IA64", L"3", DRIVER_IA64_3},
|
|
{IDS_ARCH_X86, IDS_VERSION_95_98_ME, L"Windows 4.0", L"0", DRIVER_WIN95 },
|
|
{IDS_ARCH_X86, IDS_VERSION_NT4, L"Windows NT x86", L"2", DRIVER_X86_2 },
|
|
{IDS_ARCH_X86, IDS_VERSION_W2K_XP_NET, L"Windows NT x86", L"3", DRIVER_X86_3 },
|
|
};
|
|
|
|
static TArchLV::ArchAlias aArchAlias[] =
|
|
{
|
|
{IDS_ARCH_IA64, IDS_ARCH_ITANIUM},
|
|
{IDS_ARCH_INTEL, IDS_ARCH_X86 },
|
|
{IDS_ARCH_X86_BASED, IDS_ARCH_X86 },
|
|
};
|
|
|
|
static TArchLV::VerAlias aVerAlias[] =
|
|
{
|
|
{IDS_VERSION_95_98, IDS_VERSION_95_98_ME },
|
|
{IDS_VERSION_95_98_ME_OLD, IDS_VERSION_95_98_ME },
|
|
{IDS_VERSION_NT4_W2K, IDS_VERSION_NT4 },
|
|
{IDS_VERSION_W2K, IDS_VERSION_W2K_XP_NET},
|
|
{IDS_VERSION_W2K_XP, IDS_VERSION_W2K_XP_NET},
|
|
{IDS_VERSION_XP, IDS_VERSION_XP_NET },
|
|
};
|
|
|
|
/********************************************************************
|
|
|
|
Arch List view class.
|
|
|
|
********************************************************************/
|
|
|
|
TArchLV::
|
|
TArchLV(
|
|
VOID
|
|
) : _hwnd( NULL ),
|
|
_hwndLV( NULL ),
|
|
_ColumnSortState( kMaxColumns ),
|
|
_wmDoubleClickMsg( 0 ),
|
|
_wmSingleClickMsg( 0 ),
|
|
_uCurrentColumn( 0 ),
|
|
_bNoItemCheck( FALSE )
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TArchLV::ctor\n" ) );
|
|
ArchDataList_vReset();
|
|
}
|
|
|
|
TArchLV::
|
|
~TArchLV(
|
|
VOID
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TArchLV::dtor\n" ) );
|
|
vRelease();
|
|
}
|
|
|
|
BOOL
|
|
TArchLV::
|
|
bSetUI(
|
|
IN HWND hwnd,
|
|
IN WPARAM wmDoubleClickMsg,
|
|
IN WPARAM wmSingleClickMsg
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TArchLV::bSetUI\n" ) );
|
|
|
|
SPLASSERT( hwnd );
|
|
TStatusB bStatus;
|
|
bStatus DBGNOCHK = TRUE;
|
|
|
|
//
|
|
// Save the parent window handle.
|
|
//
|
|
_hwnd = hwnd;
|
|
_wmDoubleClickMsg = wmDoubleClickMsg;
|
|
_wmSingleClickMsg = wmSingleClickMsg;
|
|
|
|
//
|
|
// Get the driver list view handle.
|
|
//
|
|
_hwndLV = GetDlgItem( _hwnd, IDC_ARCHITECTURE_LIST );
|
|
|
|
//
|
|
// Add check boxes.
|
|
//
|
|
HIMAGELIST himlState = ImageList_Create( 16, 16, TRUE, 3, 0 );
|
|
|
|
//
|
|
// !! LATER !!
|
|
// Should be created once then shared.
|
|
//
|
|
if( !himlState )
|
|
{
|
|
DBGMSG( DBG_ERROR, ( "ArchLV.bSetUI: ImageList_Create failed %d\n", GetLastError( )));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Load the bitmap for the check states.
|
|
//
|
|
HBITMAP hbm = LoadBitmap( ghInst, MAKEINTRESOURCE( IDB_CHECKSTATES ));
|
|
|
|
if( !hbm )
|
|
{
|
|
DBGMSG( DBG_ERROR, ( "ArchLV.bSetUI: LoadBitmap failed %d\n", GetLastError( )));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Add the bitmaps to the image list.
|
|
//
|
|
ImageList_AddMasked( himlState, hbm, RGB( 255, 0, 0 ));
|
|
|
|
//
|
|
// Set the new image list.
|
|
//
|
|
SendMessage( _hwndLV, LVM_SETIMAGELIST, LVSIL_STATE, (WPARAM)himlState );
|
|
|
|
//
|
|
// Remember to release the bitmap handle.
|
|
//
|
|
DeleteObject( hbm );
|
|
|
|
//
|
|
// Initialize the LV_COLUMN structure.
|
|
//
|
|
LV_COLUMN lvc;
|
|
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
|
|
lvc.fmt = LVCFMT_LEFT;
|
|
lvc.cx = kDefaultHeaderWidth;
|
|
|
|
//
|
|
// Calculate the header column width.
|
|
//
|
|
RECT rc;
|
|
if( !GetClientRect( _hwndLV, &rc ))
|
|
{
|
|
DBGMSG( DBG_WARN, ( "ArchLV.bSetUI: GetClientRect failed %d\n", GetLastError( )));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the total size of list view header, less the scroll bar.
|
|
//
|
|
LONG Interval = ( rc.right - rc.left ) - GetSystemMetrics( SM_CYVSCROLL );
|
|
|
|
//
|
|
// Column with array.
|
|
//
|
|
DWORD ColumnWidth [] = { Interval * 22, Interval * 60, Interval * 18 };
|
|
|
|
//
|
|
// Set the column header text.
|
|
//
|
|
TString strHeader;
|
|
for( INT iCol = 0; iCol < kHeaderMax; ++iCol )
|
|
{
|
|
bStatus DBGCHK = strHeader.bLoadString( ghInst, IDS_DRIVER_HEAD_ENVIRONMENT + iCol );
|
|
lvc.pszText = const_cast<LPTSTR>( static_cast<LPCTSTR>( strHeader ) );
|
|
lvc.iSubItem = iCol;
|
|
lvc.cx = ColumnWidth[iCol] / 100;
|
|
|
|
if( ListView_InsertColumn( _hwndLV, iCol, &lvc ) == -1 )
|
|
{
|
|
DBGMSG( DBG_WARN, ( "ArchLV.bSetUI: LV_Insert failed %d\n", GetLastError( )));
|
|
bStatus DBGCHK = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Enable full row selection and check boxes.
|
|
//
|
|
if( bStatus )
|
|
{
|
|
DWORD dwExStyle = ListView_GetExtendedListViewStyle( _hwndLV );
|
|
ListView_SetExtendedListViewStyle( _hwndLV, dwExStyle | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_LABELTIP );
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
BOOL
|
|
TArchLV::
|
|
bRefreshListView(
|
|
IN LPCTSTR pszServerName,
|
|
IN LPCTSTR pszDriverName
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TArchLV::bRefreshListView\n" ) );
|
|
|
|
SPLASSERT( pszDriverName );
|
|
|
|
//
|
|
// Release current list view items.
|
|
//
|
|
vRelease();
|
|
|
|
//
|
|
// Reset the sort order
|
|
//
|
|
_ColumnSortState.vResetAll();
|
|
|
|
//
|
|
// Fill the list view and sort it.
|
|
//
|
|
BOOL bReturn = bFillListView( pszServerName, pszDriverName );
|
|
|
|
//
|
|
// Sort the list view
|
|
(VOID)bListViewSort( kVersionColumn );
|
|
(VOID)bListViewSort( kArchitectureColumn );
|
|
|
|
//
|
|
// Reset the sort order
|
|
//
|
|
_ColumnSortState.vResetAll();
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
|
|
BOOL
|
|
TArchLV::
|
|
bSetCheckDefaultArch(
|
|
IN LPCTSTR pszServerName
|
|
)
|
|
{
|
|
TStatusB bStatus;
|
|
DWORD dwCurrentEncode;
|
|
TArchData *pArchData;
|
|
|
|
//
|
|
// Get the current machines architecture.
|
|
//
|
|
bStatus DBGCHK = bGetCurrentDriver( pszServerName, &dwCurrentEncode );
|
|
|
|
if( bStatus )
|
|
{
|
|
bStatus DBGNOCHK = FALSE;
|
|
|
|
DWORD cItems = ListView_GetItemCount( _hwndLV );
|
|
|
|
for( UINT i = 0; i < cItems; i++ )
|
|
{
|
|
if( bGetItemData( i, &pArchData ) )
|
|
{
|
|
if( dwCurrentEncode == pArchData->_Encode )
|
|
{
|
|
if( ( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked ) && pArchData->_bInstalled )
|
|
{
|
|
vCheckItem( i, 2 );
|
|
}
|
|
else
|
|
{
|
|
vCheckItem( i, TRUE );
|
|
}
|
|
|
|
bStatus DBGNOCHK = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return bStatus;
|
|
}
|
|
|
|
BOOL
|
|
TArchLV::
|
|
bHandleNotifyMessage(
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
BOOL bStatus = TRUE;
|
|
|
|
UNREFERENCED_PARAMETER( wParam );
|
|
|
|
switch( uMsg )
|
|
{
|
|
case WM_NOTIFY:
|
|
{
|
|
if( (INT)wParam == GetDlgCtrlID( _hwndLV ) )
|
|
{
|
|
LPNMHDR pnmh = (LPNMHDR)lParam;
|
|
|
|
switch( pnmh->code )
|
|
{
|
|
case NM_DBLCLK:
|
|
DBGMSG( DBG_TRACE, ("ArchLV::NM_DBLCLK\n" ) );
|
|
vCheckItemClicked( (LPNMHDR)lParam );
|
|
if( _wmDoubleClickMsg )
|
|
{
|
|
PostMessage( _hwnd, WM_COMMAND, _wmDoubleClickMsg, 0 );
|
|
}
|
|
break;
|
|
|
|
case NM_CLICK:
|
|
DBGMSG( DBG_TRACE, ("ArchLV::NM_CLICK\n" ) );
|
|
vCheckItemClicked( (LPNMHDR)lParam );
|
|
if( _wmSingleClickMsg )
|
|
{
|
|
PostMessage( _hwnd, WM_COMMAND, _wmSingleClickMsg, 0 );
|
|
}
|
|
break;
|
|
|
|
case LVN_COLUMNCLICK:
|
|
DBGMSG( DBG_TRACE, ("ArchLV::LVN_COLUMNCLICK\n" ) );
|
|
{
|
|
NM_LISTVIEW *pNm = (NM_LISTVIEW *)lParam;
|
|
(VOID)bListViewSort( pNm->iSubItem );
|
|
}
|
|
break;
|
|
|
|
case LVN_KEYDOWN:
|
|
DBGMSG( DBG_TRACE, ("ArchLV::LVN_KEYDOWN\n" ) );
|
|
{
|
|
if( bListVeiwKeydown( lParam ) )
|
|
{
|
|
if( _wmDoubleClickMsg )
|
|
{
|
|
PostMessage( _hwnd, WM_COMMAND, _wmDoubleClickMsg, 0 );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
bStatus = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bStatus = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
// Message not handled.
|
|
//
|
|
default:
|
|
bStatus = FALSE;
|
|
break;
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
VOID
|
|
TArchLV::
|
|
vSelectItem(
|
|
IN UINT iIndex
|
|
)
|
|
{
|
|
//
|
|
// Select the specified item.
|
|
//
|
|
if( iIndex != -1 )
|
|
{
|
|
ListView_SetItemState( _hwndLV, iIndex, LVIS_SELECTED | LVIS_FOCUSED, 0x000F );
|
|
ListView_EnsureVisible( _hwndLV, iIndex, FALSE );
|
|
}
|
|
}
|
|
|
|
VOID
|
|
TArchLV::
|
|
vNoItemCheck(
|
|
VOID
|
|
)
|
|
{
|
|
_bNoItemCheck = TRUE;
|
|
}
|
|
|
|
BOOL
|
|
TArchLV::
|
|
bEncodeToArchAndVersion(
|
|
IN DWORD dwEncode,
|
|
OUT TString &strArch,
|
|
OUT TString &strVersion
|
|
)
|
|
{
|
|
TStatusB bStatus = FALSE;
|
|
|
|
for( UINT i = 0; i < COUNTOF( aArchVerEncode ); i++ )
|
|
{
|
|
if( aArchVerEncode[i].Encode == dwEncode )
|
|
{
|
|
bStatus DBGCHK = strArch.bLoadString( ghInst, aArchVerEncode[i].ArchId );
|
|
|
|
if ( bStatus )
|
|
{
|
|
bStatus DBGCHK = strVersion.bLoadString( ghInst, aArchVerEncode[i].VerId );
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
BOOL
|
|
TArchLV::
|
|
bArchAndVersionToEncode(
|
|
OUT DWORD *pdwEncode,
|
|
IN LPCTSTR pszArchitecture,
|
|
IN LPCTSTR pszVersion,
|
|
IN BOOL bUseNonLocalizedStrings
|
|
)
|
|
{
|
|
TStatusB bStatus = FALSE;
|
|
UINT i = 0;
|
|
TString strArchitecture;
|
|
TString strMappedArchitecture;
|
|
TString strVersion;
|
|
TString strMappedVersion;
|
|
|
|
bStatus DBGCHK = pdwEncode && pszArchitecture && pszVersion;
|
|
|
|
if (bStatus)
|
|
{
|
|
if (bUseNonLocalizedStrings)
|
|
{
|
|
for (i = 0; i < COUNTOF(aArchVerEncode); i++)
|
|
{
|
|
if (!_tcsicmp(aArchVerEncode[i].NonLocalizedEnvStr, pszArchitecture) &&
|
|
!_tcsicmp(aArchVerEncode[i].NonLocalizedVerStr, pszVersion))
|
|
{
|
|
*pdwEncode = aArchVerEncode[i].Encode;
|
|
bStatus DBGCHK = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// First check for architecture alias replacement.
|
|
//
|
|
for (i = 0; i < COUNTOF(aArchAlias); i++)
|
|
{
|
|
bStatus DBGCHK = strMappedArchitecture.bLoadString(ghInst, aArchAlias[i].ArchAliasId);
|
|
if (bStatus && !_tcsicmp(strMappedArchitecture, pszArchitecture))
|
|
{
|
|
bStatus DBGCHK = strMappedArchitecture.bLoadString(ghInst, aArchAlias[i].ArchId);
|
|
if (bStatus)
|
|
{
|
|
pszArchitecture = strMappedArchitecture;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Then check for version alias replacement.
|
|
//
|
|
for (i = 0; i < COUNTOF(aVerAlias); i++)
|
|
{
|
|
bStatus DBGCHK = strMappedVersion.bLoadString(ghInst, aVerAlias[i].VerAliasId);
|
|
if (bStatus && !_tcsicmp(strMappedVersion, pszVersion))
|
|
{
|
|
bStatus DBGCHK = strMappedVersion.bLoadString(ghInst, aVerAlias[i].VerId);
|
|
if (bStatus)
|
|
{
|
|
pszVersion = strMappedVersion;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Encoding.
|
|
//
|
|
for (i = 0; i < COUNTOF(aArchVerEncode); i++)
|
|
{
|
|
bStatus DBGCHK = strArchitecture.bLoadString(ghInst, aArchVerEncode[i].ArchId);
|
|
bStatus DBGCHK = strVersion.bLoadString(ghInst, aArchVerEncode[i].VerId);
|
|
|
|
if (!_tcsicmp(strArchitecture, pszArchitecture) &&
|
|
!_tcsicmp(strVersion, pszVersion))
|
|
{
|
|
*pdwEncode = aArchVerEncode[i].Encode;
|
|
bStatus DBGCHK = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= COUNTOF(aArchVerEncode))
|
|
{
|
|
bStatus DBGCHK = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
/********************************************************************
|
|
|
|
Private member functions.
|
|
|
|
********************************************************************/
|
|
BOOL
|
|
TArchLV::
|
|
vCheckItemClicked(
|
|
IN LPNMHDR pnmh
|
|
)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
DWORD dwPoints = GetMessagePos();
|
|
POINTS &pt = MAKEPOINTS( dwPoints );
|
|
LV_HITTESTINFO lvhti;
|
|
|
|
lvhti.pt.x = pt.x;
|
|
lvhti.pt.y = pt.y;
|
|
|
|
MapWindowPoints( HWND_DESKTOP, _hwndLV, &lvhti.pt, 1 );
|
|
|
|
INT iItem = ListView_HitTest( _hwndLV, &lvhti );
|
|
|
|
//
|
|
// Allow either a double click, or a single click on the
|
|
// check box to toggle the check mark.
|
|
//
|
|
if( pnmh->code == NM_DBLCLK || lvhti.flags & LVHT_ONITEMSTATEICON )
|
|
{
|
|
vItemClicked( iItem );
|
|
bReturn = TRUE;
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
|
|
BOOL
|
|
TArchLV::
|
|
bListVeiwKeydown(
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
LV_KEYDOWN* plvnkd = (LV_KEYDOWN *)lParam;
|
|
|
|
//
|
|
// !! LATER !!
|
|
//
|
|
// Is this the best way to check whether the ALT
|
|
// key is _not_ down?
|
|
//
|
|
if( plvnkd->wVKey == TEXT( ' ' ) &&
|
|
!( GetKeyState( VK_LMENU ) & 0x80000000 ) &&
|
|
!( GetKeyState( VK_RMENU ) & 0x80000000 ))
|
|
{
|
|
//
|
|
// Get the selected item index.
|
|
//
|
|
INT iIndex = ListView_GetNextItem( _hwndLV, -1, LVNI_SELECTED );
|
|
|
|
if( iIndex != -1 )
|
|
{
|
|
vItemClicked( iIndex );
|
|
bReturn = TRUE;
|
|
}
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
VOID
|
|
TArchLV::
|
|
vRelease(
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// Release all the list view items.
|
|
//
|
|
ListView_DeleteAllItems( _hwndLV );
|
|
|
|
//
|
|
// Release the data from the architecture data list.
|
|
//
|
|
TIter Iter;
|
|
TArchData *pArchData;
|
|
|
|
for( ArchDataList_vIterInit( Iter ), Iter.vNext(); Iter.bValid(); ){
|
|
|
|
pArchData = ArchDataList_pConvert( Iter );
|
|
Iter.vNext();
|
|
|
|
delete pArchData;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
TArchLV::
|
|
bFillListView(
|
|
IN LPCTSTR pszServerName,
|
|
IN LPCTSTR pszDriverName
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TArchLV::bFillListView\n" ) );
|
|
|
|
//
|
|
// Fill the list view.
|
|
//
|
|
TStatusB bStatus;
|
|
bStatus DBGNOCHK = FALSE;
|
|
|
|
TPrinterDriverInstallation Di( pszServerName );
|
|
|
|
if( VALID_OBJ( Di ) )
|
|
{
|
|
TString strArchitecture;
|
|
TString strVersion;
|
|
TString strInstalled;
|
|
TString strNotInstalled;
|
|
LPCTSTR pszInstalled;
|
|
BOOL bInstalled;
|
|
|
|
//
|
|
// Tell the driver installation class the driver name.
|
|
//
|
|
bStatus DBGCHK = Di.bSetDriverName( pszDriverName );
|
|
|
|
//
|
|
// Load the string "(installed)" from the resource file.
|
|
//
|
|
bStatus DBGCHK = strInstalled.bLoadString( ghInst, IDS_DRIVER_INSTALLED );
|
|
bStatus DBGCHK = strNotInstalled.bLoadString( ghInst, IDS_DRIVER_NOTINSTALLED );
|
|
|
|
for( UINT i = 0; i < COUNTOF( aArchVerEncode ); i++ )
|
|
{
|
|
//
|
|
// some of the new env (like "Windows IA64") are not supported
|
|
// in the old versions of the OS, so we need to check explicitly
|
|
//
|
|
if( IDS_ARCH_ITANIUM == aArchVerEncode[i].ArchId )
|
|
{
|
|
DWORD cbBuffer = 0;
|
|
DWORD cDrivers = 0;
|
|
CAutoPtrSpl<DRIVER_INFO_3> spDI1;
|
|
|
|
if( !VDataRefresh::bEnumDrivers(pszServerName, aArchVerEncode[i].NonLocalizedEnvStr, 1,
|
|
spDI1.GetPPV(), &cbBuffer, &cDrivers) )
|
|
{
|
|
// this environment is not supported from the (remote) spooler - just skip it!
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Load the string driver name string from the resource file.
|
|
//
|
|
bStatus DBGCHK = strArchitecture.bLoadString( ghInst, aArchVerEncode[i].ArchId );
|
|
bStatus DBGCHK = strVersion.bLoadString( ghInst, aArchVerEncode[i].VerId );
|
|
|
|
//
|
|
// If the driver is installed, tell the user.
|
|
//
|
|
bInstalled = Di.bIsDriverInstalled( aArchVerEncode[i].Encode );
|
|
|
|
//
|
|
// Set the installed string.
|
|
//
|
|
pszInstalled = bInstalled ? static_cast<LPCTSTR>( strInstalled ) : static_cast<LPCTSTR>( strNotInstalled );
|
|
|
|
//
|
|
// Allocate the architecture data.
|
|
//
|
|
TArchData *pArchData = new TArchData( strArchitecture, strVersion, pszInstalled, aArchVerEncode[i].Encode, bInstalled );
|
|
|
|
//
|
|
// If valid
|
|
//
|
|
if( VALID_PTR( pArchData ) )
|
|
{
|
|
//
|
|
// Add the architecture data to the linked list.
|
|
//
|
|
ArchDataList_vAppend( pArchData );
|
|
|
|
//
|
|
// Add the string to the list view.
|
|
//
|
|
LRESULT iIndex = iAddToListView( strArchitecture, strVersion, pszInstalled, (LPARAM)pArchData );
|
|
|
|
//
|
|
// Check this item if the driver is installed.
|
|
//
|
|
if( bInstalled && (iIndex != -1) )
|
|
{
|
|
vCheckItem( iIndex, 2 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The object may have been allocated, however failed construction.
|
|
//
|
|
delete pArchData;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
LRESULT
|
|
TArchLV::
|
|
iAddToListView(
|
|
IN LPCTSTR pszArchitecture,
|
|
IN LPCTSTR pszVersion,
|
|
IN LPCTSTR pszInstalled,
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TArchLV::AddToListView\n" ) );
|
|
|
|
SPLASSERT( pszArchitecture );
|
|
SPLASSERT( pszVersion );
|
|
SPLASSERT( pszInstalled );
|
|
|
|
LV_ITEM lvi = { 0 };
|
|
|
|
//
|
|
// Add driver information to the listview.
|
|
//
|
|
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE | LVIF_STATE;
|
|
lvi.iItem = ListView_GetItemCount( _hwndLV );
|
|
lvi.pszText = const_cast<LPTSTR>( pszArchitecture );
|
|
lvi.lParam = lParam;
|
|
lvi.state = kStateUnchecked;
|
|
|
|
LRESULT iIndex = ListView_InsertItem( _hwndLV, &lvi );
|
|
if( -1 != iIndex )
|
|
{
|
|
ListView_SetItemText( _hwndLV, iIndex, 1, const_cast<LPTSTR>( pszVersion ) );
|
|
ListView_SetItemText( _hwndLV, iIndex, 2, const_cast<LPTSTR>( pszInstalled ) );
|
|
}
|
|
|
|
return iIndex;
|
|
}
|
|
|
|
BOOL
|
|
TArchLV::
|
|
bListViewSort(
|
|
UINT uColumn
|
|
)
|
|
{
|
|
//
|
|
// Set the surrent column number.
|
|
//
|
|
_uCurrentColumn = uColumn;
|
|
|
|
//
|
|
// Tell the list view to sort.
|
|
//
|
|
TStatusB bStatus;
|
|
bStatus DBGCHK = ListView_SortItems( _hwndLV, iCompareProc, (LPARAM)this );
|
|
|
|
//
|
|
// Toggle the specified column sort state.
|
|
//
|
|
_ColumnSortState.bToggle( uColumn );
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
INT
|
|
CALLBACK
|
|
TArchLV::
|
|
iCompareProc(
|
|
IN LPARAM lParam1,
|
|
IN LPARAM lParam2,
|
|
IN LPARAM RefData
|
|
)
|
|
{
|
|
TArchData *pArchData1 = reinterpret_cast<TArchData *>( lParam1 );
|
|
TArchData *pArchData2 = reinterpret_cast<TArchData *>( lParam2 );
|
|
TArchLV *pArchLV = reinterpret_cast<TArchLV *>( RefData );
|
|
INT iResult = 0;
|
|
LPCTSTR strName1 = NULL;
|
|
LPCTSTR strName2 = NULL;
|
|
|
|
if( pArchLV && pArchData1 && pArchData2 )
|
|
{
|
|
BOOL bStatus = TRUE;
|
|
|
|
switch( pArchLV->_uCurrentColumn )
|
|
{
|
|
|
|
case kArchitectureColumn:
|
|
strName1 = pArchData1->_strArchitecture;
|
|
strName2 = pArchData2->_strArchitecture;
|
|
break;
|
|
|
|
case kVersionColumn:
|
|
strName1 = pArchData1->_strVersion;
|
|
strName2 = pArchData2->_strVersion;
|
|
break;
|
|
|
|
case kInstalledColumn:
|
|
strName1 = pArchData1->_strInstalled;
|
|
strName2 = pArchData2->_strInstalled;
|
|
break;
|
|
|
|
default:
|
|
bStatus = FALSE;
|
|
break;
|
|
|
|
}
|
|
|
|
if( bStatus )
|
|
{
|
|
if( pArchLV->_ColumnSortState.bRead( pArchLV->_uCurrentColumn ) )
|
|
iResult = _tcsicmp( strName2, strName1 );
|
|
else
|
|
iResult = _tcsicmp( strName1, strName2 );
|
|
}
|
|
}
|
|
|
|
return iResult;
|
|
}
|
|
|
|
UINT
|
|
TArchLV::
|
|
uGetCheckedItemCount(
|
|
VOID
|
|
)
|
|
{
|
|
DWORD cItems = ListView_GetItemCount( _hwndLV );
|
|
|
|
UINT uItemCount = 0;
|
|
|
|
for( UINT i = 0; i < cItems; i++ )
|
|
{
|
|
if( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked )
|
|
{
|
|
uItemCount++;
|
|
}
|
|
}
|
|
return uItemCount;
|
|
}
|
|
|
|
BOOL
|
|
TArchLV::
|
|
bGetCheckedItems(
|
|
IN UINT uIndex,
|
|
IN BOOL *pbInstalled,
|
|
IN DWORD *pdwEncode
|
|
)
|
|
{
|
|
TArchData *pArchData;
|
|
UINT uItemCount = 0;
|
|
BOOL bReturn = FALSE;
|
|
|
|
DWORD cItems = ListView_GetItemCount( _hwndLV );
|
|
|
|
for( UINT i = 0; i < cItems; i++ )
|
|
{
|
|
if( ListView_GetCheckState( _hwndLV, i ) )
|
|
{
|
|
if( uItemCount++ == uIndex )
|
|
{
|
|
if( bGetItemData( i, &pArchData ) )
|
|
{
|
|
*pdwEncode = pArchData->_Encode;
|
|
*pbInstalled = pArchData->_bInstalled;
|
|
bReturn = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
BOOL
|
|
TArchLV::
|
|
bGetItemData(
|
|
IN INT iItem,
|
|
IN TArchData **ppArchData
|
|
) const
|
|
{
|
|
BOOL bStatus;
|
|
|
|
LV_ITEM lvItem = { 0 };
|
|
lvItem.mask = LVIF_PARAM;
|
|
lvItem.iItem = iItem;
|
|
|
|
bStatus = ListView_GetItem( _hwndLV, &lvItem );
|
|
|
|
if( bStatus )
|
|
{
|
|
*ppArchData = reinterpret_cast<TArchData *>( lvItem.lParam );
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
/*++
|
|
|
|
Name:
|
|
|
|
vItemClicked
|
|
|
|
Routine Description:
|
|
|
|
User clicked in listview. Check if item state should
|
|
be changed.
|
|
|
|
The item will also be selected.
|
|
|
|
Arguments:
|
|
|
|
iItem - Item that has been clicked.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
VOID
|
|
TArchLV::
|
|
vItemClicked(
|
|
IN INT iItem
|
|
)
|
|
{
|
|
TStatusB bStatus;
|
|
TArchData *pArchData;
|
|
|
|
//
|
|
// Do nothing when an invalid index is passed.
|
|
//
|
|
if( iItem != -1 && !_bNoItemCheck )
|
|
{
|
|
//
|
|
// Retrieve the old state, toggle it, then set it.
|
|
//
|
|
DWORD dwState = ListView_GetItemState( _hwndLV, iItem, kStateMask );
|
|
|
|
//
|
|
// Get the item data.
|
|
//
|
|
bStatus DBGCHK = bGetItemData( iItem, &pArchData );
|
|
|
|
//
|
|
// If item data was fetched.
|
|
//
|
|
if( bStatus && pArchData )
|
|
{
|
|
//
|
|
// Only allow checking of the item that are not installed.
|
|
//
|
|
if( !pArchData->_bInstalled )
|
|
{
|
|
//
|
|
// Toggle the current state.
|
|
//
|
|
vCheckItem( iItem, dwState != kStateChecked );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Name:
|
|
|
|
vCheckItem
|
|
|
|
Routine Description:
|
|
|
|
Change the specified items check state.
|
|
|
|
Arguments:
|
|
|
|
iItem - Item index to change the check state for.
|
|
bCheckState - The new item check state, TRUE check, FALSE uncheck.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
VOID
|
|
TArchLV::
|
|
vCheckItem(
|
|
IN INT iItem,
|
|
IN BOOL bCheckState
|
|
)
|
|
{
|
|
//
|
|
// Do nothing when an invalid index is passed.
|
|
//
|
|
if( iItem != -1 )
|
|
{
|
|
if( bCheckState == 2 )
|
|
{
|
|
//
|
|
// Set the new check state.
|
|
//
|
|
ListView_SetItemState( _hwndLV, iItem, kStateDisabled, kStateMask | LVIS_SELECTED | LVIS_FOCUSED );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Set the item check state.
|
|
//
|
|
DWORD dwState = bCheckState ? kStateChecked | LVIS_SELECTED | LVIS_FOCUSED : kStateUnchecked | LVIS_SELECTED | LVIS_FOCUSED;
|
|
|
|
//
|
|
// Set the new check state.
|
|
//
|
|
ListView_SetItemState( _hwndLV, iItem, dwState, kStateMask | LVIS_SELECTED | LVIS_FOCUSED );
|
|
}
|
|
}
|
|
|
|
/********************************************************************
|
|
|
|
Architecure data.
|
|
|
|
********************************************************************/
|
|
TArchLV::TArchData::
|
|
TArchData(
|
|
IN LPCTSTR pszArchitecture,
|
|
IN LPCTSTR pszVersion,
|
|
IN LPCTSTR pszInstalled,
|
|
IN DWORD Encode,
|
|
IN BOOL bInstalled
|
|
) : _strArchitecture( pszArchitecture ),
|
|
_strVersion( pszVersion ),
|
|
_strInstalled( pszInstalled ),
|
|
_Encode( Encode ),
|
|
_bInstalled( bInstalled )
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TArchLV::TArchData::ctor\n" ) );
|
|
}
|
|
|
|
TArchLV::TArchData::
|
|
~TArchData(
|
|
VOID
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "TArchLV::TArchData::dtor\n" ) );
|
|
|
|
//
|
|
// If we are linked then remove ourself.
|
|
//
|
|
if( ArchData_bLinked() )
|
|
{
|
|
ArchData_vDelinkSelf();
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
TArchLV::TArchData::
|
|
bValid(
|
|
VOID
|
|
)
|
|
{
|
|
return VALID_OBJ( _strArchitecture ) &&
|
|
VALID_OBJ( _strVersion ) &&
|
|
VALID_OBJ( _strInstalled );
|
|
}
|
|
|