Source code of Windows XP (NT5)
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.

1109 lines
26 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1998
  3. All rights reserved.
  4. Module Name:
  5. archlv.hxx
  6. Abstract:
  7. Driver Architecture List View
  8. Author:
  9. Steve Kiraly (SteveKi) 19-Nov-1996
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "psetup.hxx"
  15. #include "drvsetup.hxx"
  16. #include "drvver.hxx"
  17. #include "archlv.hxx"
  18. /********************************************************************
  19. Arch List - static data.
  20. ********************************************************************/
  21. //
  22. // disable MIPS & PPC drivers, since they are not supported from setup
  23. //
  24. static TArchLV::ArchEncode aArchEncode[] =
  25. {
  26. {IDS_ARCH_IA64, IDS_VERSION_51, L"Windows IA64", L"3", DRIVER_IA64_3 },
  27. {IDS_ARCH_INTEL, IDS_VERSION_WINDOWS_ME, L"Windows 4.0", L"0", DRIVER_WIN95 },
  28. {IDS_ARCH_INTEL, IDS_VERSION_40_50, L"Windows NT x86", L"2", DRIVER_X86_2 },
  29. {IDS_ARCH_INTEL, IDS_VERSION_50_51, L"Windows NT x86", L"3", DRIVER_X86_3 },
  30. {IDS_ARCH_ALPHA, IDS_VERSION_40, L"Windows NT Alpha_AXP", L"2", DRIVER_ALPHA_2 },
  31. #if FALSE
  32. {IDS_ARCH_INTEL, IDS_VERSION_NT_31, L"Windows NT x86", L"1", DRIVER_X86_0 },
  33. {IDS_ARCH_INTEL, IDS_VERSION_35X, L"Windows NT x86", L"1", DRIVER_X86_1 },
  34. {IDS_ARCH_MIPS, IDS_VERSION_NT_31, L"Windows NT R4000", L"1", DRIVER_MIPS_0 },
  35. {IDS_ARCH_MIPS, IDS_VERSION_35X, L"Windows NT R4000", L"1", DRIVER_MIPS_1 },
  36. {IDS_ARCH_MIPS, IDS_VERSION_40, L"Windows NT R4000", L"2", DRIVER_MIPS_2 },
  37. {IDS_ARCH_ALPHA, IDS_VERSION_NT_31, L"Windows NT Alpha_AXP", L"1", DRIVER_ALPHA_0 },
  38. {IDS_ARCH_ALPHA, IDS_VERSION_35X, L"Windows NT Alpha_AXP", L"1", DRIVER_ALPHA_1 },
  39. {IDS_ARCH_POWERPC, IDS_VERSION_351, L"Windows NT PowerPC", L"1", DRIVER_PPC_1 },
  40. {IDS_ARCH_POWERPC, IDS_VERSION_40, L"Windows NT PowerPC", L"2", DRIVER_PPC_2 },
  41. #endif
  42. };
  43. // use this aliases for the driver version string, so we don't break
  44. // admin scripts written for Win2k.
  45. static DWORD aVersionAliases[] =
  46. {
  47. IDS_VERSION_WINDOWS_95, IDS_VERSION_WINDOWS_ME,
  48. IDS_VERSION_40, IDS_VERSION_40_50,
  49. IDS_VERSION_50, IDS_VERSION_50_51,
  50. };
  51. /********************************************************************
  52. Arch List view class.
  53. ********************************************************************/
  54. TArchLV::
  55. TArchLV(
  56. VOID
  57. ) : _hwnd( NULL ),
  58. _hwndLV( NULL ),
  59. _ColumnSortState( kMaxColumns ),
  60. _wmDoubleClickMsg( 0 ),
  61. _wmSingleClickMsg( 0 ),
  62. _uCurrentColumn( 0 ),
  63. _bNoItemCheck( FALSE )
  64. {
  65. DBGMSG( DBG_TRACE, ( "TArchLV::ctor\n" ) );
  66. ArchDataList_vReset();
  67. }
  68. TArchLV::
  69. ~TArchLV(
  70. VOID
  71. )
  72. {
  73. DBGMSG( DBG_TRACE, ( "TArchLV::dtor\n" ) );
  74. vRelease();
  75. }
  76. BOOL
  77. TArchLV::
  78. bSetUI(
  79. IN HWND hwnd,
  80. IN WPARAM wmDoubleClickMsg,
  81. IN WPARAM wmSingleClickMsg
  82. )
  83. {
  84. DBGMSG( DBG_TRACE, ( "TArchLV::bSetUI\n" ) );
  85. SPLASSERT( hwnd );
  86. TStatusB bStatus;
  87. bStatus DBGNOCHK = TRUE;
  88. //
  89. // Save the parent window handle.
  90. //
  91. _hwnd = hwnd;
  92. _wmDoubleClickMsg = wmDoubleClickMsg;
  93. _wmSingleClickMsg = wmSingleClickMsg;
  94. //
  95. // Get the driver list view handle.
  96. //
  97. _hwndLV = GetDlgItem( _hwnd, IDC_ARCHITECTURE_LIST );
  98. //
  99. // Add check boxes.
  100. //
  101. HIMAGELIST himlState = ImageList_Create( 16, 16, TRUE, 3, 0 );
  102. //
  103. // !! LATER !!
  104. // Should be created once then shared.
  105. //
  106. if( !himlState )
  107. {
  108. DBGMSG( DBG_ERROR, ( "ArchLV.bSetUI: ImageList_Create failed %d\n", GetLastError( )));
  109. return FALSE;
  110. }
  111. //
  112. // Load the bitmap for the check states.
  113. //
  114. HBITMAP hbm = LoadBitmap( ghInst, MAKEINTRESOURCE( IDB_CHECKSTATES ));
  115. if( !hbm )
  116. {
  117. DBGMSG( DBG_ERROR, ( "ArchLV.bSetUI: LoadBitmap failed %d\n", GetLastError( )));
  118. return FALSE;
  119. }
  120. //
  121. // Add the bitmaps to the image list.
  122. //
  123. ImageList_AddMasked( himlState, hbm, RGB( 255, 0, 0 ));
  124. //
  125. // Set the new image list.
  126. //
  127. SendMessage( _hwndLV, LVM_SETIMAGELIST, LVSIL_STATE, (WPARAM)himlState );
  128. //
  129. // Remember to release the bitmap handle.
  130. //
  131. DeleteObject( hbm );
  132. //
  133. // Initialize the LV_COLUMN structure.
  134. //
  135. LV_COLUMN lvc;
  136. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  137. lvc.fmt = LVCFMT_LEFT;
  138. lvc.cx = kDefaultHeaderWidth;
  139. //
  140. // Calculate the header column width.
  141. //
  142. RECT rc;
  143. if( !GetClientRect( _hwndLV, &rc ))
  144. {
  145. DBGMSG( DBG_WARN, ( "ArchLV.bSetUI: GetClientRect failed %d\n", GetLastError( )));
  146. return FALSE;
  147. }
  148. //
  149. // Get the total size of list view header, less the scroll bar.
  150. //
  151. LONG Interval = ( rc.right - rc.left ) - GetSystemMetrics( SM_CYVSCROLL );
  152. //
  153. // Column with array.
  154. //
  155. DWORD ColumnWidth [] = { Interval * 25, Interval * 55, Interval * 20 };
  156. //
  157. // Set the column header text.
  158. //
  159. TString strHeader;
  160. for( INT iCol = 0; iCol < kHeaderMax; ++iCol )
  161. {
  162. bStatus DBGCHK = strHeader.bLoadString( ghInst, IDS_DRIVER_HEAD_ENVIRONMENT + iCol );
  163. lvc.pszText = const_cast<LPTSTR>( static_cast<LPCTSTR>( strHeader ) );
  164. lvc.iSubItem = iCol;
  165. lvc.cx = ColumnWidth[iCol] / 100;
  166. if( ListView_InsertColumn( _hwndLV, iCol, &lvc ) == -1 )
  167. {
  168. DBGMSG( DBG_WARN, ( "ArchLV.bSetUI: LV_Insert failed %d\n", GetLastError( )));
  169. bStatus DBGCHK = FALSE;
  170. }
  171. }
  172. //
  173. // Enable full row selection and check boxes.
  174. //
  175. if( bStatus )
  176. {
  177. DWORD dwExStyle = ListView_GetExtendedListViewStyle( _hwndLV );
  178. ListView_SetExtendedListViewStyle( _hwndLV, dwExStyle | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_LABELTIP );
  179. }
  180. return bStatus;
  181. }
  182. BOOL
  183. TArchLV::
  184. bRefreshListView(
  185. IN LPCTSTR pszServerName,
  186. IN LPCTSTR pszDriverName
  187. )
  188. {
  189. DBGMSG( DBG_TRACE, ( "TArchLV::bRefreshListView\n" ) );
  190. SPLASSERT( pszDriverName );
  191. //
  192. // Release current list view items.
  193. //
  194. vRelease();
  195. //
  196. // Reset the sort order
  197. //
  198. _ColumnSortState.vResetAll();
  199. //
  200. // Fill the list view and sort it.
  201. //
  202. BOOL bReturn = bFillListView( pszServerName, pszDriverName );
  203. //
  204. // Sort the list view
  205. (VOID)bListViewSort( kVersionColumn );
  206. (VOID)bListViewSort( kArchitectureColumn );
  207. //
  208. // Reset the sort order
  209. //
  210. _ColumnSortState.vResetAll();
  211. return bReturn;
  212. }
  213. BOOL
  214. TArchLV::
  215. bSetCheckDefaultArch(
  216. IN LPCTSTR pszServerName
  217. )
  218. {
  219. TStatusB bStatus;
  220. DWORD dwCurrentEncode;
  221. TArchData *pArchData;
  222. //
  223. // Get the current machines architecture.
  224. //
  225. bStatus DBGCHK = bGetCurrentDriver( pszServerName, &dwCurrentEncode );
  226. if( bStatus )
  227. {
  228. bStatus DBGNOCHK = FALSE;
  229. DWORD cItems = ListView_GetItemCount( _hwndLV );
  230. for( UINT i = 0; i < cItems; i++ )
  231. {
  232. if( bGetItemData( i, &pArchData ) )
  233. {
  234. if( dwCurrentEncode == pArchData->_Encode )
  235. {
  236. if( ( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked ) && pArchData->_bInstalled )
  237. {
  238. vCheckItem( i, 2 );
  239. }
  240. else
  241. {
  242. vCheckItem( i, TRUE );
  243. }
  244. bStatus DBGNOCHK = TRUE;
  245. break;
  246. }
  247. }
  248. }
  249. }
  250. return bStatus;
  251. }
  252. BOOL
  253. TArchLV::
  254. bHandleNotifyMessage(
  255. IN UINT uMsg,
  256. IN WPARAM wParam,
  257. IN LPARAM lParam
  258. )
  259. {
  260. BOOL bStatus = TRUE;
  261. UNREFERENCED_PARAMETER( wParam );
  262. switch( uMsg )
  263. {
  264. case WM_NOTIFY:
  265. {
  266. if( (INT)wParam == GetDlgCtrlID( _hwndLV ) )
  267. {
  268. LPNMHDR pnmh = (LPNMHDR)lParam;
  269. switch( pnmh->code )
  270. {
  271. case NM_DBLCLK:
  272. DBGMSG( DBG_TRACE, ("ArchLV::NM_DBLCLK\n" ) );
  273. vCheckItemClicked( (LPNMHDR)lParam );
  274. if( _wmDoubleClickMsg )
  275. {
  276. PostMessage( _hwnd, WM_COMMAND, _wmDoubleClickMsg, 0 );
  277. }
  278. break;
  279. case NM_CLICK:
  280. DBGMSG( DBG_TRACE, ("ArchLV::NM_CLICK\n" ) );
  281. vCheckItemClicked( (LPNMHDR)lParam );
  282. if( _wmSingleClickMsg )
  283. {
  284. PostMessage( _hwnd, WM_COMMAND, _wmSingleClickMsg, 0 );
  285. }
  286. break;
  287. case LVN_COLUMNCLICK:
  288. DBGMSG( DBG_TRACE, ("ArchLV::LVN_COLUMNCLICK\n" ) );
  289. {
  290. NM_LISTVIEW *pNm = (NM_LISTVIEW *)lParam;
  291. (VOID)bListViewSort( pNm->iSubItem );
  292. }
  293. break;
  294. case LVN_KEYDOWN:
  295. DBGMSG( DBG_TRACE, ("ArchLV::LVN_KEYDOWN\n" ) );
  296. {
  297. if( bListVeiwKeydown( lParam ) )
  298. {
  299. if( _wmDoubleClickMsg )
  300. {
  301. PostMessage( _hwnd, WM_COMMAND, _wmDoubleClickMsg, 0 );
  302. }
  303. }
  304. }
  305. break;
  306. default:
  307. bStatus = FALSE;
  308. break;
  309. }
  310. }
  311. else
  312. {
  313. bStatus = FALSE;
  314. }
  315. }
  316. break;
  317. //
  318. // Message not handled.
  319. //
  320. default:
  321. bStatus = FALSE;
  322. break;
  323. }
  324. return bStatus;
  325. }
  326. VOID
  327. TArchLV::
  328. vSelectItem(
  329. IN UINT iIndex
  330. )
  331. {
  332. //
  333. // Select the specified item.
  334. //
  335. if( iIndex != -1 )
  336. {
  337. ListView_SetItemState( _hwndLV, iIndex, LVIS_SELECTED | LVIS_FOCUSED, 0x000F );
  338. ListView_EnsureVisible( _hwndLV, iIndex, FALSE );
  339. }
  340. }
  341. VOID
  342. TArchLV::
  343. vNoItemCheck(
  344. VOID
  345. )
  346. {
  347. _bNoItemCheck = TRUE;
  348. }
  349. BOOL
  350. TArchLV::
  351. bEncodeToArchAndVersion(
  352. IN DWORD dwEncode,
  353. OUT TString &strArch,
  354. OUT TString &strVersion
  355. )
  356. {
  357. TStatusB bStatus;
  358. bStatus DBGNOCHK = FALSE;
  359. for( UINT i = 0; i < COUNTOF( aArchEncode ); i++ )
  360. {
  361. if( aArchEncode[i].Encode == dwEncode )
  362. {
  363. bStatus DBGCHK = strArch.bLoadString( ghInst, aArchEncode[i].ArchId );
  364. bStatus DBGCHK = strVersion.bLoadString( ghInst, aArchEncode[i].VersionId );
  365. break;
  366. }
  367. }
  368. return bStatus;
  369. }
  370. BOOL
  371. TArchLV::
  372. bArchAndVersionToEncode(
  373. OUT DWORD *pdwEncode,
  374. IN LPCTSTR pszArchitecture,
  375. IN LPCTSTR pszVersion,
  376. IN BOOL bUseNonLocalizedStrings
  377. )
  378. {
  379. BOOL bReturn = FALSE;
  380. TString strArch;
  381. TString strVersion;
  382. TStatusB bStatus;
  383. if (pdwEncode && pszArchitecture && pszVersion)
  384. {
  385. if (bUseNonLocalizedStrings)
  386. {
  387. for (UINT i = 0; i < COUNTOF(aArchEncode); i++)
  388. {
  389. if (!_tcsicmp(aArchEncode[i].NonLocalizedEnvironment, pszArchitecture) &&
  390. !_tcsicmp(aArchEncode[i].NonLocalizedVersion, pszVersion))
  391. {
  392. *pdwEncode = aArchEncode[i].Encode;
  393. bReturn = TRUE;
  394. break;
  395. }
  396. }
  397. }
  398. else
  399. {
  400. UINT i;
  401. TString strMappedVersion;
  402. // check to remap the version string if necessary.
  403. for (i = 0; (i+1) < COUNTOF( aVersionAliases ); i+=2)
  404. {
  405. bStatus DBGCHK = strMappedVersion.bLoadString(ghInst, aVersionAliases[i]);
  406. if( bStatus && 0 == lstrcmp(strMappedVersion, pszVersion) )
  407. {
  408. // this version string was remapped, map to the new string.
  409. bStatus DBGCHK = strMappedVersion.bLoadString(ghInst, aVersionAliases[i+1]);
  410. if( bStatus )
  411. {
  412. pszVersion = strMappedVersion;
  413. }
  414. }
  415. }
  416. // find the arch & version, and do the encode
  417. for (i = 0; i < COUNTOF( aArchEncode ); i++)
  418. {
  419. bStatus DBGCHK = strArch.bLoadString(ghInst, aArchEncode[i].ArchId);
  420. bStatus DBGCHK = strVersion.bLoadString(ghInst, aArchEncode[i].VersionId);
  421. if (!_tcsicmp(strArch, pszArchitecture) && !_tcsicmp(strVersion, pszVersion))
  422. {
  423. *pdwEncode = aArchEncode[i].Encode;
  424. bReturn = TRUE;
  425. break;
  426. }
  427. }
  428. }
  429. }
  430. return bReturn;
  431. }
  432. BOOL
  433. TArchLV::
  434. bGetEncodeFromIndex(
  435. IN UINT uIndex,
  436. OUT DWORD *pdwEncode
  437. )
  438. {
  439. BOOL bReturn = FALSE;
  440. //
  441. // Validate the passed in index.
  442. //
  443. if( uIndex < COUNTOF( aArchEncode ) )
  444. {
  445. //
  446. // Return back the encode for the given index.
  447. //
  448. *pdwEncode = aArchEncode[uIndex].Encode;
  449. bReturn = TRUE;
  450. }
  451. return bReturn;
  452. }
  453. /********************************************************************
  454. Private member functions.
  455. ********************************************************************/
  456. BOOL
  457. TArchLV::
  458. vCheckItemClicked(
  459. IN LPNMHDR pnmh
  460. )
  461. {
  462. BOOL bReturn = FALSE;
  463. DWORD dwPoints = GetMessagePos();
  464. POINTS &pt = MAKEPOINTS( dwPoints );
  465. LV_HITTESTINFO lvhti;
  466. lvhti.pt.x = pt.x;
  467. lvhti.pt.y = pt.y;
  468. MapWindowPoints( HWND_DESKTOP, _hwndLV, &lvhti.pt, 1 );
  469. INT iItem = ListView_HitTest( _hwndLV, &lvhti );
  470. //
  471. // Allow either a double click, or a single click on the
  472. // check box to toggle the check mark.
  473. //
  474. if( pnmh->code == NM_DBLCLK || lvhti.flags & LVHT_ONITEMSTATEICON )
  475. {
  476. vItemClicked( iItem );
  477. bReturn = TRUE;
  478. }
  479. return bReturn;
  480. }
  481. BOOL
  482. TArchLV::
  483. bListVeiwKeydown(
  484. IN LPARAM lParam
  485. )
  486. {
  487. BOOL bReturn = FALSE;
  488. LV_KEYDOWN* plvnkd = (LV_KEYDOWN *)lParam;
  489. //
  490. // !! LATER !!
  491. //
  492. // Is this the best way to check whether the ALT
  493. // key is _not_ down?
  494. //
  495. if( plvnkd->wVKey == TEXT( ' ' ) &&
  496. !( GetKeyState( VK_LMENU ) & 0x80000000 ) &&
  497. !( GetKeyState( VK_RMENU ) & 0x80000000 ))
  498. {
  499. //
  500. // Get the selected item index.
  501. //
  502. INT iIndex = ListView_GetNextItem( _hwndLV, -1, LVNI_SELECTED );
  503. if( iIndex != -1 )
  504. {
  505. vItemClicked( iIndex );
  506. bReturn = TRUE;
  507. }
  508. }
  509. return bReturn;
  510. }
  511. VOID
  512. TArchLV::
  513. vRelease(
  514. VOID
  515. )
  516. {
  517. //
  518. // Release all the list view items.
  519. //
  520. ListView_DeleteAllItems( _hwndLV );
  521. //
  522. // Release the data from the architecture data list.
  523. //
  524. TIter Iter;
  525. TArchData *pArchData;
  526. for( ArchDataList_vIterInit( Iter ), Iter.vNext(); Iter.bValid(); ){
  527. pArchData = ArchDataList_pConvert( Iter );
  528. Iter.vNext();
  529. delete pArchData;
  530. }
  531. }
  532. BOOL
  533. TArchLV::
  534. bFillListView(
  535. IN LPCTSTR pszServerName,
  536. IN LPCTSTR pszDriverName
  537. )
  538. {
  539. DBGMSG( DBG_TRACE, ( "TArchLV::bFillListView\n" ) );
  540. //
  541. // Fill the list view.
  542. //
  543. TStatusB bStatus;
  544. bStatus DBGNOCHK = FALSE;
  545. TPrinterDriverInstallation Di( pszServerName );
  546. if( VALID_OBJ( Di ) )
  547. {
  548. TString strArchitecture;
  549. TString strVersion;
  550. TString strInstalled;
  551. TString strNotInstalled;
  552. LPCTSTR pszInstalled;
  553. BOOL bInstalled;
  554. //
  555. // Tell the driver installation class the driver name.
  556. //
  557. bStatus DBGCHK = Di.bSetDriverName( pszDriverName );
  558. //
  559. // Load the string "(installed)" from the resource file.
  560. //
  561. bStatus DBGCHK = strInstalled.bLoadString( ghInst, IDS_DRIVER_INSTALLED );
  562. bStatus DBGCHK = strNotInstalled.bLoadString( ghInst, IDS_DRIVER_NOTINSTALLED );
  563. for( UINT i = 0; i < COUNTOF( aArchEncode ); i++ )
  564. {
  565. //
  566. // some of the new env (like "Windows IA64") are not supported
  567. // in the old versions of the OS, so we need to check explicitly
  568. //
  569. if( IDS_ARCH_IA64 == aArchEncode[i].ArchId )
  570. {
  571. DWORD cbBuffer = 0;
  572. DWORD cDrivers = 0;
  573. CAutoPtrSpl<DRIVER_INFO_3> spDI1;
  574. if( !VDataRefresh::bEnumDrivers(pszServerName, aArchEncode[i].NonLocalizedEnvironment, 1,
  575. spDI1.GetPPV(), &cbBuffer, &cDrivers) )
  576. {
  577. // this environment is not supported from the (remote) spooler - just skip it!
  578. continue;
  579. }
  580. }
  581. //
  582. // Load the string driver name string from the resource file.
  583. //
  584. bStatus DBGCHK = strArchitecture.bLoadString( ghInst, aArchEncode[i].ArchId );
  585. bStatus DBGCHK = strVersion.bLoadString( ghInst, aArchEncode[i].VersionId );
  586. //
  587. // If the driver is installed, tell the user.
  588. //
  589. bInstalled = Di.bIsDriverInstalled( aArchEncode[i].Encode );
  590. //
  591. // Set the installed string.
  592. //
  593. pszInstalled = bInstalled ? static_cast<LPCTSTR>( strInstalled ) : static_cast<LPCTSTR>( strNotInstalled );
  594. //
  595. // Allocate the architecture data.
  596. //
  597. TArchData *pArchData = new TArchData( strArchitecture, strVersion, pszInstalled, aArchEncode[i].Encode, bInstalled );
  598. //
  599. // If valid
  600. //
  601. if( VALID_PTR( pArchData ) )
  602. {
  603. //
  604. // Add the architecture data to the linked list.
  605. //
  606. ArchDataList_vAppend( pArchData );
  607. //
  608. // Add the string to the list view.
  609. //
  610. LRESULT iIndex = iAddToListView( strArchitecture, strVersion, pszInstalled, (LPARAM)pArchData );
  611. //
  612. // Check this item if the driver is installed.
  613. //
  614. if( bInstalled && (iIndex != -1) )
  615. {
  616. vCheckItem( iIndex, 2 );
  617. }
  618. }
  619. else
  620. {
  621. //
  622. // The object may have been allocated, however failed construction.
  623. //
  624. delete pArchData;
  625. }
  626. }
  627. }
  628. return bStatus;
  629. }
  630. LRESULT
  631. TArchLV::
  632. iAddToListView(
  633. IN LPCTSTR pszArchitecture,
  634. IN LPCTSTR pszVersion,
  635. IN LPCTSTR pszInstalled,
  636. IN LPARAM lParam
  637. )
  638. {
  639. DBGMSG( DBG_TRACE, ( "TArchLV::AddToListView\n" ) );
  640. SPLASSERT( pszArchitecture );
  641. SPLASSERT( pszVersion );
  642. SPLASSERT( pszInstalled );
  643. LV_ITEM lvi = { 0 };
  644. //
  645. // Add driver information to the listview.
  646. //
  647. lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE | LVIF_STATE;
  648. lvi.iItem = ListView_GetItemCount( _hwndLV );
  649. lvi.pszText = const_cast<LPTSTR>( pszArchitecture );
  650. lvi.lParam = lParam;
  651. lvi.state = kStateUnchecked;
  652. LRESULT iIndex = ListView_InsertItem( _hwndLV, &lvi );
  653. if( -1 != iIndex )
  654. {
  655. ListView_SetItemText( _hwndLV, iIndex, 1, const_cast<LPTSTR>( pszVersion ) );
  656. ListView_SetItemText( _hwndLV, iIndex, 2, const_cast<LPTSTR>( pszInstalled ) );
  657. }
  658. return iIndex;
  659. }
  660. BOOL
  661. TArchLV::
  662. bListViewSort(
  663. UINT uColumn
  664. )
  665. {
  666. //
  667. // Set the surrent column number.
  668. //
  669. _uCurrentColumn = uColumn;
  670. //
  671. // Tell the list view to sort.
  672. //
  673. TStatusB bStatus;
  674. bStatus DBGCHK = ListView_SortItems( _hwndLV, iCompareProc, (LPARAM)this );
  675. //
  676. // Toggle the specified column sort state.
  677. //
  678. _ColumnSortState.bToggle( uColumn );
  679. return bStatus;
  680. }
  681. INT
  682. CALLBACK
  683. TArchLV::
  684. iCompareProc(
  685. IN LPARAM lParam1,
  686. IN LPARAM lParam2,
  687. IN LPARAM RefData
  688. )
  689. {
  690. TArchData *pArchData1 = reinterpret_cast<TArchData *>( lParam1 );
  691. TArchData *pArchData2 = reinterpret_cast<TArchData *>( lParam2 );
  692. TArchLV *pArchLV = reinterpret_cast<TArchLV *>( RefData );
  693. INT iResult = 0;
  694. LPCTSTR strName1 = NULL;
  695. LPCTSTR strName2 = NULL;
  696. if( pArchLV && pArchData1 && pArchData2 )
  697. {
  698. BOOL bStatus = TRUE;
  699. switch( pArchLV->_uCurrentColumn )
  700. {
  701. case kArchitectureColumn:
  702. strName1 = pArchData1->_strArchitecture;
  703. strName2 = pArchData2->_strArchitecture;
  704. break;
  705. case kVersionColumn:
  706. strName1 = pArchData1->_strVersion;
  707. strName2 = pArchData2->_strVersion;
  708. break;
  709. case kInstalledColumn:
  710. strName1 = pArchData1->_strInstalled;
  711. strName2 = pArchData2->_strInstalled;
  712. break;
  713. default:
  714. bStatus = FALSE;
  715. break;
  716. }
  717. if( bStatus )
  718. {
  719. if( pArchLV->_ColumnSortState.bRead( pArchLV->_uCurrentColumn ) )
  720. iResult = _tcsicmp( strName2, strName1 );
  721. else
  722. iResult = _tcsicmp( strName1, strName2 );
  723. }
  724. }
  725. return iResult;
  726. }
  727. UINT
  728. TArchLV::
  729. uGetCheckedItemCount(
  730. VOID
  731. )
  732. {
  733. DWORD cItems = ListView_GetItemCount( _hwndLV );
  734. UINT uItemCount = 0;
  735. for( UINT i = 0; i < cItems; i++ )
  736. {
  737. if( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked )
  738. {
  739. uItemCount++;
  740. }
  741. }
  742. return uItemCount;
  743. }
  744. BOOL
  745. TArchLV::
  746. bGetCheckedItems(
  747. IN UINT uIndex,
  748. IN BOOL *pbInstalled,
  749. IN DWORD *pdwEncode
  750. )
  751. {
  752. TArchData *pArchData;
  753. UINT uItemCount = 0;
  754. BOOL bReturn = FALSE;
  755. DWORD cItems = ListView_GetItemCount( _hwndLV );
  756. for( UINT i = 0; i < cItems; i++ )
  757. {
  758. if( ListView_GetCheckState( _hwndLV, i ) )
  759. {
  760. if( uItemCount++ == uIndex )
  761. {
  762. if( bGetItemData( i, &pArchData ) )
  763. {
  764. *pdwEncode = pArchData->_Encode;
  765. *pbInstalled = pArchData->_bInstalled;
  766. bReturn = TRUE;
  767. break;
  768. }
  769. }
  770. }
  771. }
  772. return bReturn;
  773. }
  774. BOOL
  775. TArchLV::
  776. bGetItemData(
  777. IN INT iItem,
  778. IN TArchData **ppArchData
  779. ) const
  780. {
  781. BOOL bStatus;
  782. LV_ITEM lvItem = { 0 };
  783. lvItem.mask = LVIF_PARAM;
  784. lvItem.iItem = iItem;
  785. bStatus = ListView_GetItem( _hwndLV, &lvItem );
  786. if( bStatus )
  787. {
  788. *ppArchData = reinterpret_cast<TArchData *>( lvItem.lParam );
  789. }
  790. return bStatus;
  791. }
  792. /*++
  793. Name:
  794. vItemClicked
  795. Routine Description:
  796. User clicked in listview. Check if item state should
  797. be changed.
  798. The item will also be selected.
  799. Arguments:
  800. iItem - Item that has been clicked.
  801. Return Value:
  802. Nothing.
  803. --*/
  804. VOID
  805. TArchLV::
  806. vItemClicked(
  807. IN INT iItem
  808. )
  809. {
  810. TStatusB bStatus;
  811. TArchData *pArchData;
  812. //
  813. // Do nothing when an invalid index is passed.
  814. //
  815. if( iItem != -1 && !_bNoItemCheck )
  816. {
  817. //
  818. // Retrieve the old state, toggle it, then set it.
  819. //
  820. DWORD dwState = ListView_GetItemState( _hwndLV, iItem, kStateMask );
  821. //
  822. // Get the item data.
  823. //
  824. bStatus DBGCHK = bGetItemData( iItem, &pArchData );
  825. //
  826. // If item data was fetched.
  827. //
  828. if( bStatus && pArchData )
  829. {
  830. //
  831. // Only allow checking of the item that are not installed.
  832. //
  833. if( !pArchData->_bInstalled )
  834. {
  835. //
  836. // Toggle the current state.
  837. //
  838. vCheckItem( iItem, dwState != kStateChecked );
  839. }
  840. }
  841. }
  842. }
  843. /*++
  844. Name:
  845. vCheckItem
  846. Routine Description:
  847. Change the specified items check state.
  848. Arguments:
  849. iItem - Item index to change the check state for.
  850. bCheckState - The new item check state, TRUE check, FALSE uncheck.
  851. Return Value:
  852. Nothing.
  853. --*/
  854. VOID
  855. TArchLV::
  856. vCheckItem(
  857. IN INT iItem,
  858. IN BOOL bCheckState
  859. )
  860. {
  861. //
  862. // Do nothing when an invalid index is passed.
  863. //
  864. if( iItem != -1 )
  865. {
  866. if( bCheckState == 2 )
  867. {
  868. //
  869. // Set the new check state.
  870. //
  871. ListView_SetItemState( _hwndLV, iItem, kStateDisabled, kStateMask | LVIS_SELECTED | LVIS_FOCUSED );
  872. return;
  873. }
  874. //
  875. // Set the item check state.
  876. //
  877. DWORD dwState = bCheckState ? kStateChecked | LVIS_SELECTED | LVIS_FOCUSED : kStateUnchecked | LVIS_SELECTED | LVIS_FOCUSED;
  878. //
  879. // Set the new check state.
  880. //
  881. ListView_SetItemState( _hwndLV, iItem, dwState, kStateMask | LVIS_SELECTED | LVIS_FOCUSED );
  882. }
  883. }
  884. /********************************************************************
  885. Architecure data.
  886. ********************************************************************/
  887. TArchLV::TArchData::
  888. TArchData(
  889. IN LPCTSTR pszArchitecture,
  890. IN LPCTSTR pszVersion,
  891. IN LPCTSTR pszInstalled,
  892. IN DWORD Encode,
  893. IN BOOL bInstalled
  894. ) : _strArchitecture( pszArchitecture ),
  895. _strVersion( pszVersion ),
  896. _strInstalled( pszInstalled ),
  897. _Encode( Encode ),
  898. _bInstalled( bInstalled )
  899. {
  900. DBGMSG( DBG_TRACE, ( "TArchLV::TArchData::ctor\n" ) );
  901. }
  902. TArchLV::TArchData::
  903. ~TArchData(
  904. VOID
  905. )
  906. {
  907. DBGMSG( DBG_TRACE, ( "TArchLV::TArchData::dtor\n" ) );
  908. //
  909. // If we are linked then remove ourself.
  910. //
  911. if( ArchData_bLinked() )
  912. {
  913. ArchData_vDelinkSelf();
  914. }
  915. }
  916. BOOL
  917. TArchLV::TArchData::
  918. bValid(
  919. VOID
  920. )
  921. {
  922. return VALID_OBJ( _strArchitecture ) &&
  923. VALID_OBJ( _strVersion ) &&
  924. VALID_OBJ( _strInstalled );
  925. }