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.

1225 lines
27 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. All rights reserved.
  4. Module Name:
  5. driverlv.hxx
  6. Abstract:
  7. Driver List View
  8. Author:
  9. Steve Kiraly (SteveKi) 19-Nov-1996
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "driverif.hxx"
  15. #include "driverlv.hxx"
  16. #include "compinfo.hxx"
  17. /********************************************************************
  18. Drivers List view class.
  19. ********************************************************************/
  20. TDriversLV::
  21. TDriversLV(
  22. VOID
  23. ) : _hwnd( NULL ),
  24. _hwndLV( NULL ),
  25. _cLVDrivers( 0 ),
  26. _ColumnSortState( kMaxColumn ),
  27. _uCurrentColumn( 0 )
  28. {
  29. DBGMSG( DBG_TRACE, ( "TDriversLV::ctor\n" ) );
  30. DriverInfoList_vReset();
  31. }
  32. TDriversLV::
  33. ~TDriversLV(
  34. VOID
  35. )
  36. {
  37. DBGMSG( DBG_TRACE, ( "TDriversLV::dtor\n" ) );
  38. vRelease();
  39. }
  40. BOOL
  41. TDriversLV::
  42. bSetUI(
  43. IN LPCTSTR pszServerName,
  44. IN HWND hwnd,
  45. IN WPARAM wmDoubleClickMsg,
  46. IN WPARAM wmSingleClickMsg,
  47. IN WPARAM wmDeleteKeyMsg
  48. )
  49. {
  50. SPLASSERT( hwnd );
  51. //
  52. // Save the parent window handle.
  53. //
  54. _strServerName.bUpdate( pszServerName );
  55. _hwnd = hwnd;
  56. _wmDoubleClickMsg = wmDoubleClickMsg;
  57. _wmSingleClickMsg = wmSingleClickMsg;
  58. _wmDeleteKeyMsg = wmDeleteKeyMsg;
  59. //
  60. // Get the driver list view handle.
  61. //
  62. _hwndLV = GetDlgItem( _hwnd, IDC_DRIVERS );
  63. //
  64. // Initialize the LV_COLUMN structure.
  65. //
  66. LV_COLUMN lvc;
  67. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  68. lvc.fmt = LVCFMT_LEFT;
  69. lvc.cx = kDriverDefaultHeaderWidth;
  70. //
  71. // Set the column header text.
  72. //
  73. TStatusB bStatus;
  74. bStatus DBGNOCHK = TRUE;
  75. TString strHeader;
  76. for( INT iCol = 0; iCol < kDriverHeaderMax; ++iCol )
  77. {
  78. bStatus DBGCHK = strHeader.bLoadString( ghInst, IDS_DRIVER_HEAD_NAME + iCol );
  79. lvc.pszText = const_cast<LPTSTR>( static_cast<LPCTSTR>( strHeader ) );
  80. lvc.iSubItem = iCol;
  81. if( ListView_InsertColumn( _hwndLV, iCol, &lvc ) == -1 )
  82. {
  83. DBGMSG( DBG_WARN, ( "DriversLV.bSetUI: LV_Insert failed %d\n", GetLastError( )));
  84. bStatus DBGCHK = FALSE;
  85. }
  86. }
  87. //
  88. // Enable full row selection.
  89. //
  90. if( bStatus )
  91. {
  92. DWORD dwExStyle = ListView_GetExtendedListViewStyle( _hwndLV );
  93. ListView_SetExtendedListViewStyle( _hwndLV, dwExStyle | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_LABELTIP );
  94. }
  95. return bStatus;
  96. }
  97. UINT
  98. TDriversLV::
  99. uGetListViewItemCount(
  100. VOID
  101. ) const
  102. {
  103. return _cLVDrivers;
  104. }
  105. BOOL
  106. TDriversLV::
  107. bIsAnyItemSelcted(
  108. VOID
  109. ) const
  110. {
  111. INT iIndex = -1;
  112. return bGetSelectedItem( &iIndex );
  113. }
  114. VOID
  115. TDriversLV::
  116. vSelectItem(
  117. IN UINT iIndex
  118. )
  119. {
  120. //
  121. // Select the specified item.
  122. //
  123. if( iIndex != -1 )
  124. {
  125. ListView_SetItemState( _hwndLV, iIndex, LVIS_SELECTED | LVIS_FOCUSED, 0x000F );
  126. ListView_EnsureVisible( _hwndLV, iIndex, FALSE );
  127. }
  128. }
  129. BOOL
  130. TDriversLV::
  131. bRefresh(
  132. VOID
  133. )
  134. {
  135. TStatusB bStatus;
  136. //
  137. // Release all the list view items.
  138. //
  139. vDeleteAllListViewItems();
  140. //
  141. // Load the new list view data.
  142. //
  143. bStatus DBGCHK = bLoadDrivers();
  144. //
  145. // This array of numbers represents the percentages of
  146. // each column width from the total LV width. The sum
  147. // of all numbers in the array should be equal to 100
  148. // (100% = the total LV width)
  149. //
  150. UINT arrColumnWidths[] = { 38, 22, 40 };
  151. //
  152. // Adjust the header column widths here
  153. //
  154. vAdjustHeaderColumns( _hwndLV, COUNTOF(arrColumnWidths), arrColumnWidths );
  155. return bStatus;
  156. }
  157. BOOL
  158. TDriversLV::
  159. bAddDriverInfoToListView(
  160. TDriverInfo *pDriverInfo, ADOPT
  161. BOOL bCheckForDuplicates
  162. )
  163. {
  164. SPLASSERT( pDriverInfo );
  165. //
  166. // Should we check for duplicates before adding the driver.
  167. //
  168. if( bCheckForDuplicates )
  169. {
  170. TDriverInfo *pDrvInfo = NULL;
  171. if( bFindDriverInfo( pDriverInfo, &pDrvInfo ) )
  172. {
  173. //
  174. // A duplicate was found release the duplicatate,
  175. // the new one has precedence.
  176. //
  177. if( pDrvInfo )
  178. {
  179. vDeleteDriverInfoFromListView( pDrvInfo );
  180. delete pDrvInfo;
  181. }
  182. }
  183. }
  184. //
  185. // Append the driver info to the list.
  186. //
  187. vAddInSortedOrder( pDriverInfo );
  188. //
  189. // Add the driver info to the list view.
  190. //
  191. vAddDriverToListView( pDriverInfo );
  192. return TRUE;
  193. }
  194. BOOL
  195. TDriversLV::
  196. bAddDriverInfoToListView(
  197. IN TDriverTransfer &DriverTransfer
  198. )
  199. {
  200. TIter Iter;
  201. TDriverInfo *pDriverInfo;
  202. DriverTransfer.DriverInfoList_vIterInit( Iter );
  203. for( Iter.vNext(); Iter.bValid(); )
  204. {
  205. pDriverInfo = DriverTransfer.DriverInfoList_pConvert( Iter );
  206. Iter.vNext();
  207. //
  208. // If the driver info is linked then unlink it.
  209. //
  210. if( pDriverInfo->DriverInfo_bLinked() )
  211. {
  212. pDriverInfo->DriverInfo_vDelinkSelf();
  213. }
  214. //
  215. // Add driver to the list view UI.
  216. //
  217. (VOID)bAddDriverInfoToListView( pDriverInfo, TRUE );
  218. }
  219. return TRUE;
  220. }
  221. BOOL
  222. TDriversLV::
  223. bGetSelectedDriverInfo(
  224. IN TDriverInfo **ppDriverInfo,
  225. IN TDriversLV::THandle &Handle
  226. ) const
  227. {
  228. SPLASSERT( ppDriverInfo );
  229. BOOL bStatus = FALSE;
  230. INT iIndex = Handle.Index();
  231. if( bGetSelectedItem( &iIndex ) )
  232. {
  233. if( bGetItemData( iIndex, ppDriverInfo ) )
  234. {
  235. if( *ppDriverInfo )
  236. {
  237. Handle.Index( iIndex );
  238. bStatus = TRUE;
  239. }
  240. }
  241. }
  242. return bStatus;
  243. }
  244. BOOL
  245. TDriversLV::
  246. bGetSelectedDriverInfo(
  247. IN TDriverTransfer &DriverTransfer,
  248. IN UINT *pnCount OPTIONAL
  249. )
  250. {
  251. TDriverInfo *pDriverInfo;
  252. TDriversLV::THandle Handle;
  253. TStatusB bStatus;
  254. UINT nCount = 0;
  255. for( bStatus DBGNOCHK = TRUE; bStatus ; )
  256. {
  257. //
  258. // Remove the selected items from the list.
  259. //
  260. bStatus DBGNOCHK = bGetSelectedDriverInfo( &pDriverInfo, Handle );
  261. if( bStatus )
  262. {
  263. //
  264. // Tallay the selected item count.
  265. //
  266. nCount++;
  267. //
  268. // If the driver info is linked then unlink it.
  269. //
  270. if( pDriverInfo->DriverInfo_bLinked() )
  271. {
  272. pDriverInfo->DriverInfo_vDelinkSelf();
  273. }
  274. //
  275. // Append the driver info to the transfer list.
  276. //
  277. DriverTransfer.DriverInfoList_vAppend( pDriverInfo );
  278. }
  279. }
  280. //
  281. // If the caller wants the count of the number of
  282. // elements placed on the transfer list.
  283. //
  284. if( pnCount )
  285. {
  286. *pnCount = nCount;
  287. }
  288. //
  289. // If any items were placed on the transfer list then return success.
  290. //
  291. return nCount ? TRUE : FALSE;
  292. }
  293. UINT
  294. TDriversLV::
  295. uGetSelectedDriverInfoCount(
  296. VOID
  297. ) const
  298. {
  299. TDriverInfo *pDriverInfo;
  300. TDriversLV::THandle Handle;
  301. TStatusB bStatus;
  302. UINT nCount = 0;
  303. for( bStatus DBGNOCHK = TRUE; bStatus ; )
  304. {
  305. //
  306. // Remove the selected items from the list.
  307. //
  308. bStatus DBGCHK = bGetSelectedDriverInfo( &pDriverInfo, Handle );
  309. if( bStatus )
  310. {
  311. //
  312. // Tallay the selected item count.
  313. //
  314. nCount++;
  315. }
  316. }
  317. return nCount;
  318. }
  319. VOID
  320. TDriversLV::
  321. vDeleteDriverInfoFromListView(
  322. IN TDriverInfo *pDriverInfo
  323. )
  324. {
  325. SPLASSERT( pDriverInfo );
  326. //
  327. // Locate the driver name in the list view.
  328. //
  329. INT iItem = iFindDriver ( pDriverInfo );
  330. if( iItem != -1 )
  331. {
  332. //
  333. // Adjust the list view item count.
  334. //
  335. _cLVDrivers--;
  336. //
  337. // Delete the item.
  338. //
  339. ListView_DeleteItem( _hwndLV, iItem );
  340. //
  341. // Get the list view item count.
  342. //
  343. INT iItemCount = ListView_GetItemCount( _hwndLV );
  344. //
  345. // Select next item. If the item we just deleted is the last item,
  346. // we need to select the previous one.
  347. //
  348. // If we deleted the last item, leave it as is.
  349. //
  350. if( iItemCount == iItem && iItem > 0 )
  351. {
  352. --iItem;
  353. }
  354. //
  355. // Select the adjacent item.
  356. //
  357. vSelectItem( iItem );
  358. //
  359. // If there is no items in the list veiw send click notification.
  360. // The client may need to disable buttons that apply to selected
  361. // items.
  362. //
  363. if( iItemCount == 0 )
  364. {
  365. PostMessage( _hwnd, WM_COMMAND, _wmSingleClickMsg, 0 );
  366. }
  367. }
  368. }
  369. VOID
  370. TDriversLV::
  371. vDeleteDriverInfoFromListView(
  372. IN TDriverTransfer &DriverTransfer
  373. )
  374. {
  375. TIter Iter;
  376. TDriverInfo *pDriverInfo;
  377. DriverTransfer.DriverInfoList_vIterInit( Iter );
  378. for( Iter.vNext(); Iter.bValid(); )
  379. {
  380. pDriverInfo = DriverTransfer.DriverInfoList_pConvert( Iter );
  381. Iter.vNext();
  382. //
  383. // If the driver info is linked then unlink it.
  384. //
  385. if( pDriverInfo->DriverInfo_bLinked() )
  386. {
  387. pDriverInfo->DriverInfo_vDelinkSelf();
  388. }
  389. //
  390. // Append the driver info to the list no UI.
  391. //
  392. vAddInSortedOrder( pDriverInfo );
  393. //
  394. // Delete this driver from the UI part of the list view.
  395. //
  396. vDeleteDriverInfoFromListView( pDriverInfo );
  397. }
  398. }
  399. VOID
  400. TDriversLV::
  401. vReturnDriverInfoToListView(
  402. IN TDriverInfo *pDriverInfo
  403. )
  404. {
  405. SPLASSERT( pDriverInfo );
  406. if( pDriverInfo )
  407. {
  408. //
  409. // If the driver info is linked then unlink it.
  410. //
  411. if( pDriverInfo->DriverInfo_bLinked() )
  412. {
  413. pDriverInfo->DriverInfo_vDelinkSelf();
  414. }
  415. //
  416. // Append the driver info to the list no UI.
  417. //
  418. vAddInSortedOrder( pDriverInfo );
  419. }
  420. }
  421. VOID
  422. TDriversLV::
  423. vReturnDriverInfoToListView(
  424. IN TDriverTransfer &DriverTransfer
  425. )
  426. {
  427. TIter Iter;
  428. TDriverInfo *pDriverInfo;
  429. DriverTransfer.DriverInfoList_vIterInit( Iter );
  430. for( Iter.vNext(); Iter.bValid(); )
  431. {
  432. pDriverInfo = DriverTransfer.DriverInfoList_pConvert( Iter );
  433. Iter.vNext();
  434. //
  435. // If the driver info is linked then unlink it.
  436. //
  437. if( pDriverInfo->DriverInfo_bLinked() )
  438. {
  439. pDriverInfo->DriverInfo_vDelinkSelf();
  440. }
  441. //
  442. // Append the driver info to the list no UI.
  443. //
  444. vAddInSortedOrder( pDriverInfo );
  445. }
  446. }
  447. BOOL
  448. TDriversLV::
  449. bHandleMessage(
  450. IN UINT uMsg,
  451. IN WPARAM wParam,
  452. IN LPARAM lParam
  453. )
  454. {
  455. BOOL bStatus = TRUE;
  456. UNREFERENCED_PARAMETER( wParam );
  457. switch( uMsg )
  458. {
  459. case WM_NOTIFY:
  460. {
  461. if( (INT)wParam == GetDlgCtrlID( _hwndLV ) )
  462. {
  463. LPNMHDR pnmh = (LPNMHDR)lParam;
  464. switch( pnmh->code )
  465. {
  466. case NM_DBLCLK:
  467. DBGMSG( DBG_NONE, ("DriversLV::NM_DBLCLK\n" ) );
  468. if( _wmDoubleClickMsg )
  469. {
  470. PostMessage( _hwnd, WM_COMMAND, _wmDoubleClickMsg, 0 );
  471. }
  472. break;
  473. case NM_CLICK:
  474. DBGMSG( DBG_NONE, ("DriversLV::NM_CLICK\n" ) );
  475. if( _wmSingleClickMsg )
  476. {
  477. PostMessage( _hwnd, WM_COMMAND, _wmSingleClickMsg, 0 );
  478. }
  479. break;
  480. case LVN_COLUMNCLICK:
  481. DBGMSG( DBG_NONE, ("DriversLV::LVN_COLUMNCLICK\n" ) );
  482. {
  483. NM_LISTVIEW *pNm = (NM_LISTVIEW *)lParam;
  484. (VOID)bDriverListViewSort( pNm->iSubItem );
  485. }
  486. break;
  487. case LVN_ITEMCHANGED:
  488. DBGMSG( DBG_NONE, ( "DriversLV::LVN_ITEMCHANGED\n" ) );
  489. {
  490. NM_LISTVIEW *pNm = (NM_LISTVIEW *)lParam;
  491. if( pNm->uNewState & LVIS_SELECTED )
  492. {
  493. PostMessage( _hwnd, WM_COMMAND, _wmSingleClickMsg, 0 );
  494. }
  495. }
  496. break;
  497. case LVN_KEYDOWN:
  498. DBGMSG( DBG_NONE, ("DriversLV::LVN_KEYDOWN\n" ) );
  499. if( ((LPNMLVKEYDOWN)pnmh)->wVKey == VK_DELETE )
  500. {
  501. if( _wmDeleteKeyMsg )
  502. {
  503. PostMessage( _hwnd, WM_COMMAND, _wmDeleteKeyMsg, 0 );
  504. }
  505. }
  506. break;
  507. default:
  508. bStatus = FALSE;
  509. break;
  510. }
  511. }
  512. else
  513. {
  514. bStatus = FALSE;
  515. }
  516. }
  517. break;
  518. //
  519. // Message not handled.
  520. //
  521. default:
  522. bStatus = FALSE;
  523. break;
  524. }
  525. return bStatus;
  526. }
  527. VOID
  528. TDriversLV::
  529. vDeleteAllListViewItems(
  530. VOID
  531. )
  532. {
  533. //
  534. // Clear the item count.
  535. //
  536. _cLVDrivers = 0;
  537. //
  538. // Reset the column sort state.
  539. //
  540. _ColumnSortState.vResetAll();
  541. //
  542. // Delete all the items from the UI control.
  543. //
  544. ListView_DeleteAllItems( _hwndLV );
  545. //
  546. // Release all the list view data.
  547. //
  548. vRelease();
  549. }
  550. BOOL
  551. TDriversLV::
  552. bSortColumn(
  553. IN const EColumns Column,
  554. IN const EOrder Order
  555. )
  556. {
  557. //
  558. // Set the sort order.
  559. //
  560. if( Order == kAscending )
  561. {
  562. _ColumnSortState.bSet( Column );
  563. }
  564. else
  565. {
  566. _ColumnSortState.bReset( Column );
  567. }
  568. //
  569. // Sort the driver list.
  570. //
  571. return bDriverListViewSort( static_cast<UINT>( Column ) );
  572. }
  573. BOOL
  574. TDriversLV::
  575. bSendDriverInfoNotification(
  576. IN TDriversLVNotify &Notify
  577. ) const
  578. {
  579. BOOL bStatus = TRUE;
  580. TDriverInfo *pDriverInfo;
  581. //
  582. // Initialize the list iterator.
  583. //
  584. TIter Iter;
  585. DriverInfoList_vIterInit( Iter );
  586. //
  587. // Iterate the added drivers.
  588. //
  589. for( Iter.vNext(); bStatus && Iter.bValid(); )
  590. {
  591. pDriverInfo = DriverInfoList_pConvert( Iter );
  592. Iter.vNext();
  593. SPLASSERT( pDriverInfo );
  594. if( !Notify.bNotify( pDriverInfo ) )
  595. {
  596. bStatus = FALSE;
  597. break;
  598. }
  599. }
  600. return bStatus;
  601. }
  602. BOOL
  603. TDriversLV::
  604. bGetFullDriverList(
  605. IN TDriverTransfer &DriverTransfer,
  606. IN UINT *pnCount OPTIONAL
  607. )
  608. {
  609. TDriverInfo *pDriverInfo = NULL;
  610. UINT nCount = 0;
  611. //
  612. // Initialize the list iterator.
  613. //
  614. TIter Iter;
  615. DriverInfoList_vIterInit( Iter );
  616. //
  617. // Iterate the added drivers.
  618. //
  619. for( Iter.vNext(); Iter.bValid(); )
  620. {
  621. pDriverInfo = DriverInfoList_pConvert( Iter );
  622. SPLASSERT( pDriverInfo );
  623. Iter.vNext();
  624. //
  625. // If the driver info is linked then unlink it.
  626. //
  627. if( pDriverInfo->DriverInfo_bLinked() )
  628. {
  629. pDriverInfo->DriverInfo_vDelinkSelf();
  630. }
  631. //
  632. // Tally the number of drivers.
  633. //
  634. nCount++;
  635. //
  636. // Append the driver info to the transfer list.
  637. //
  638. DriverTransfer.DriverInfoList_vAppend( pDriverInfo );
  639. }
  640. //
  641. // If the caller wants the count of the number of
  642. // elements placed on the transfer list.
  643. //
  644. if( pnCount )
  645. {
  646. *pnCount = nCount;
  647. }
  648. //
  649. // If any items were placed on the transfer list then return success.
  650. //
  651. return nCount ? TRUE : FALSE;
  652. }
  653. VOID
  654. TDriversLV::
  655. vDumpList(
  656. VOID
  657. )
  658. {
  659. #if DBG
  660. //
  661. // Release everything from the driver info list.
  662. //
  663. TIter Iter;
  664. TDriverInfo *pDriverInfo;
  665. DriverInfoList_vIterInit( Iter );
  666. for( Iter.vNext(); Iter.bValid(); Iter.vNext() )
  667. {
  668. pDriverInfo = DriverInfoList_pConvert( Iter );
  669. DBGMSG( DBG_TRACE, ( "N " TSTR " E " TSTR " V %d T %d\n", (LPCTSTR)pDriverInfo->strName(), (LPCTSTR)pDriverInfo->strEnv(), pDriverInfo->dwVersion(), pDriverInfo->vGetInfoState() ) );
  670. }
  671. #endif
  672. }
  673. /********************************************************************
  674. Private member functions.
  675. ********************************************************************/
  676. VOID
  677. TDriversLV::
  678. vRelease(
  679. VOID
  680. )
  681. {
  682. //
  683. // Release everything from the driver info list.
  684. //
  685. TIter Iter;
  686. TDriverInfo *pDriverInfo;
  687. for( DriverInfoList_vIterInit( Iter ), Iter.vNext(); Iter.bValid(); )
  688. {
  689. pDriverInfo = DriverInfoList_pConvert( Iter );
  690. Iter.vNext();
  691. delete pDriverInfo;
  692. }
  693. }
  694. BOOL
  695. TDriversLV::
  696. bLoadDrivers(
  697. VOID
  698. )
  699. {
  700. TStatusB bStatus;
  701. bStatus DBGNOCHK = TRUE;
  702. LPCTSTR aEnv[] = { { ENVIRONMENT_INTEL },
  703. { ENVIRONMENT_MIPS },
  704. { ENVIRONMENT_ALPHA },
  705. { ENVIRONMENT_POWERPC },
  706. { ENVIRONMENT_WINDOWS },
  707. { ENVIRONMENT_IA64 } };
  708. for( UINT index = 0; index < COUNTOF( aEnv ); ++index )
  709. {
  710. TDriverInfo *pDriverInfo = NULL;
  711. PDRIVER_INFO_3 pDriverEnumInfo = NULL;
  712. DWORD cbBuffer = 0;
  713. DWORD cDrivers = 0;
  714. PVOID pInfo = NULL;
  715. UINT uLevel = kEnumDriversLevel;
  716. for( bStatus DBGNOCHK = TRUE ; bStatus; uLevel = 2 )
  717. {
  718. //
  719. // Enumerate all the available drivers.
  720. //
  721. bStatus DBGCHK = VDataRefresh::bEnumDrivers( _strServerName,
  722. const_cast<LPTSTR>( aEnv[index] ),
  723. uLevel,
  724. (VOID **)&pDriverEnumInfo,
  725. &cbBuffer,
  726. &cDrivers );
  727. //
  728. // If the call failed because of an invalid level then try another level.
  729. //
  730. if( !bStatus && GetLastError() == ERROR_INVALID_LEVEL && uLevel > 2 )
  731. {
  732. bStatus DBGNOCHK = TRUE;
  733. }
  734. else
  735. {
  736. //
  737. // In the remote case all environments may not be supported.
  738. //
  739. if( !bStatus && GetLastError() == ERROR_INVALID_ENVIRONMENT )
  740. {
  741. bStatus DBGNOCHK = TRUE;
  742. break;
  743. }
  744. else
  745. {
  746. break;
  747. }
  748. }
  749. }
  750. if( bStatus )
  751. {
  752. LPCTSTR pszDrvName = NULL;
  753. if( cDrivers )
  754. {
  755. for( UINT i = 0; i < cDrivers; ++i )
  756. {
  757. //
  758. // Index to the next driver info structure using the level as a guide.
  759. //
  760. switch( uLevel )
  761. {
  762. case 2:
  763. pInfo = (PCHAR)pDriverEnumInfo + ( sizeof( DRIVER_INFO_2 ) * i );
  764. pszDrvName = reinterpret_cast<DRIVER_INFO_2*>(pInfo)->pName;
  765. break;
  766. case 3:
  767. pInfo = (PCHAR)pDriverEnumInfo + ( sizeof( DRIVER_INFO_3 ) * i );
  768. pszDrvName = reinterpret_cast<DRIVER_INFO_3*>(pInfo)->pName;
  769. break;
  770. default:
  771. pInfo = NULL;
  772. pszDrvName = NULL;
  773. break;
  774. }
  775. if( pInfo && pszDrvName && 0 != lstrcmp(pszDrvName, FAX_DRIVER_NAME) )
  776. {
  777. //
  778. // Create a driver info structure.
  779. //
  780. pDriverInfo = new TDriverInfo( TDriverInfo::kInstalled, uLevel, pInfo );
  781. if( VALID_PTR( pDriverInfo ) )
  782. {
  783. //
  784. // Add the driver information to the list view. This will orphan the
  785. // driver info class to the driver info list which TDriverLV maintains.
  786. //
  787. bStatus DBGCHK = bAddDriverInfoToListView( pDriverInfo, FALSE );
  788. }
  789. else
  790. {
  791. //
  792. // The object may have been allocated, however failed construction.
  793. //
  794. delete pDriverInfo;
  795. }
  796. }
  797. }
  798. }
  799. //
  800. // We release the enumeration structure because the driver info data is
  801. // duplicated in the TDriverInfo class.
  802. //
  803. FreeMem( pDriverEnumInfo );
  804. }
  805. }
  806. return bStatus;
  807. }
  808. VOID
  809. TDriversLV::
  810. vAddDriverToListView(
  811. IN TDriverInfo *pDriverInfo
  812. )
  813. {
  814. DBGMSG( DBG_TRACE, ( "TDriversLV::AddDriverToListView\n" ) );
  815. SPLASSERT( pDriverInfo );
  816. //
  817. // Add driver information to the listview.
  818. //
  819. LV_ITEM lvi = {0};
  820. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  821. lvi.iItem = _cLVDrivers;
  822. lvi.pszText = const_cast<LPTSTR>( static_cast<LPCTSTR>( pDriverInfo->strName() ) );
  823. lvi.lParam = reinterpret_cast<LPARAM>( pDriverInfo );
  824. ListView_InsertItem( _hwndLV, &lvi );
  825. ListView_SetItemText( _hwndLV, _cLVDrivers, 1, const_cast<LPTSTR>( static_cast<LPCTSTR>( pDriverInfo->strEnvironment() ) ) );
  826. ListView_SetItemText( _hwndLV, _cLVDrivers, 2, const_cast<LPTSTR>( static_cast<LPCTSTR>( pDriverInfo->strVersion() ) ) );
  827. ++_cLVDrivers;
  828. }
  829. BOOL
  830. TDriversLV::
  831. bGetItemData(
  832. IN INT iItem,
  833. IN TDriverInfo **ppDriverInfo
  834. ) const
  835. {
  836. SPLASSERT( ppDriverInfo );
  837. BOOL bStatus;
  838. LV_ITEM lvItem = { 0 };
  839. lvItem.mask = LVIF_PARAM;
  840. lvItem.iItem = iItem;
  841. bStatus = ListView_GetItem( _hwndLV, &lvItem );
  842. if( bStatus )
  843. {
  844. *ppDriverInfo = reinterpret_cast<TDriverInfo *>( lvItem.lParam );
  845. }
  846. return bStatus;
  847. }
  848. BOOL
  849. TDriversLV::
  850. bDriverListViewSort(
  851. UINT uColumn
  852. )
  853. {
  854. //
  855. // Set the current column.
  856. //
  857. _uCurrentColumn = uColumn;
  858. //
  859. // Tell the list view to sort.
  860. //
  861. TStatusB bStatus;
  862. bStatus DBGCHK = ListView_SortItems( _hwndLV, iCompareProc, (LPARAM)this );
  863. //
  864. // Toggle the specified column sort state.
  865. //
  866. _ColumnSortState.bToggle( uColumn );
  867. return bStatus;
  868. }
  869. BOOL
  870. TDriversLV::
  871. bGetSelectedItem(
  872. IN INT *pIndex
  873. ) const
  874. {
  875. BOOL bStatus = FALSE;
  876. INT iItem = ListView_GetNextItem( _hwndLV, *pIndex, LVNI_SELECTED );
  877. if( iItem != -1 )
  878. {
  879. bStatus = TRUE;
  880. *pIndex = iItem;
  881. }
  882. return bStatus;
  883. }
  884. INT
  885. CALLBACK
  886. TDriversLV::
  887. iCompareProc(
  888. IN LPARAM lParam1,
  889. IN LPARAM lParam2,
  890. IN LPARAM RefData
  891. )
  892. {
  893. TDriversLV *pDriversLV = reinterpret_cast<TDriversLV *>( RefData );
  894. TDriverInfo *pDriverInfo1 = reinterpret_cast<TDriverInfo *>( lParam1 );
  895. TDriverInfo *pDriverInfo2 = reinterpret_cast<TDriverInfo *>( lParam2 );
  896. INT iResult = 0;
  897. DWORD dwNumber1 = 0;
  898. DWORD dwNumber2 = 0;
  899. LPCTSTR strName1 = NULL;
  900. LPCTSTR strName2 = NULL;
  901. BOOL bNumeric = FALSE;
  902. if( pDriversLV && pDriverInfo1 && pDriverInfo2 )
  903. {
  904. BOOL bStatus = TRUE;
  905. switch( pDriversLV->_uCurrentColumn )
  906. {
  907. case kDriverNameColumn:
  908. strName1 = pDriverInfo1->strName();
  909. strName2 = pDriverInfo2->strName();
  910. break;
  911. case kEnvironmentColumn:
  912. strName1 = pDriverInfo1->strEnvironment();
  913. strName2 = pDriverInfo2->strEnvironment();
  914. break;
  915. case kVersionColumn:
  916. dwNumber1 = pDriverInfo1->dwVersion();
  917. dwNumber2 = pDriverInfo2->dwVersion();
  918. bNumeric = TRUE;
  919. break;
  920. default:
  921. bStatus = FALSE;
  922. break;
  923. }
  924. if( bStatus )
  925. {
  926. if( pDriversLV->_ColumnSortState.bRead( pDriversLV->_uCurrentColumn ) )
  927. {
  928. if( bNumeric )
  929. iResult = dwNumber1 - dwNumber2;
  930. else
  931. iResult = _tcsicmp( strName1, strName2 );
  932. }
  933. else
  934. {
  935. if( bNumeric )
  936. iResult = dwNumber2 - dwNumber1;
  937. else
  938. iResult = _tcsicmp( strName2, strName1 );
  939. }
  940. }
  941. }
  942. return iResult;
  943. }
  944. /*++
  945. Name:
  946. iFindDriver
  947. Routine Description:
  948. Located the specified driver info structure in the list view.
  949. Arguments:
  950. pDriverInfo - pointer to driver info structure to find.
  951. Return Value:
  952. iItem id if found, -1 if item was not found.
  953. --*/
  954. INT
  955. TDriversLV::
  956. iFindDriver(
  957. IN TDriverInfo *pDriverInfo
  958. ) const
  959. {
  960. SPLASSERT( pDriverInfo );
  961. LV_FINDINFO lvfi = { 0 };
  962. lvfi.flags = LVFI_PARAM;
  963. lvfi.lParam = (LPARAM)pDriverInfo;
  964. //
  965. // Locate the driver item.
  966. //
  967. INT iItem = ListView_FindItem( _hwndLV, -1, &lvfi );
  968. if( iItem == -1 )
  969. {
  970. DBGMSG( DBG_WARN, ( "DriverLV.iFindDriver: failed not found\n" ) );
  971. }
  972. return iItem;
  973. }
  974. BOOL
  975. TDriversLV::
  976. bFindDriverInfo(
  977. IN TDriverInfo *pDriverInfo,
  978. IN OUT TDriverInfo **ppDriverInfo
  979. ) const
  980. {
  981. BOOL bStatus = FALSE;
  982. TIter Iter;
  983. TDriverInfo *pDrvInfo;
  984. for( DriverInfoList_vIterInit( Iter ), Iter.vNext(); Iter.bValid(); Iter.vNext() )
  985. {
  986. pDrvInfo = DriverInfoList_pConvert( Iter );
  987. if( *pDriverInfo == *pDrvInfo )
  988. {
  989. *ppDriverInfo = pDrvInfo;
  990. bStatus = TRUE;
  991. break;
  992. }
  993. }
  994. return bStatus;
  995. }
  996. VOID
  997. TDriversLV::
  998. vAddInSortedOrder(
  999. IN TDriverInfo *pDriverInfo
  1000. )
  1001. {
  1002. BOOL bInserted = FALSE;
  1003. TIter Iter;
  1004. TDriverInfo *pDrvInfo;
  1005. DriverInfoList_vIterInit( Iter );
  1006. for( Iter.vNext(); Iter.bValid(); Iter.vNext() )
  1007. {
  1008. pDrvInfo = DriverInfoList_pConvert( Iter );
  1009. if( *pDrvInfo > *pDriverInfo )
  1010. {
  1011. DriverInfoList_vInsertBefore( Iter, pDriverInfo );
  1012. bInserted = TRUE;
  1013. break;
  1014. }
  1015. }
  1016. if( !bInserted )
  1017. {
  1018. DriverInfoList_vAppend( pDriverInfo );
  1019. }
  1020. }
  1021. /********************************************************************
  1022. Drivers List View Notify class.
  1023. ********************************************************************/
  1024. TDriversLVNotify::
  1025. TDriversLVNotify(
  1026. VOID
  1027. )
  1028. {
  1029. }
  1030. TDriversLVNotify::
  1031. ~TDriversLVNotify(
  1032. VOID
  1033. )
  1034. {
  1035. }