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.

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