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.

2182 lines
45 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. All rights reserved.
  4. Module Name:
  5. portslv.hxx
  6. Abstract:
  7. Ports List View header
  8. Author:
  9. Albert Ting (AlbertT) 17-Aug-1995
  10. Steve Kiraly (SteveKi) 29-Mar-1996
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #include "portslv.hxx"
  16. #if DBG
  17. //#define DBG_PORTSINFO DBG_INFO
  18. #define DBG_PORTSINFO DBG_NONE
  19. #endif
  20. MSG_ERRMAP gaMsgErrMapPorts[] = {
  21. ERROR_NOT_SUPPORTED, IDS_ERR_PORT_NOT_IMPLEMENTED,
  22. ERROR_ALREADY_EXISTS, IDS_ERR_PORT_ALREADY_EXISTS,
  23. 0, 0
  24. };
  25. /********************************************************************
  26. Ports List view class.
  27. ********************************************************************/
  28. TPortsLV::
  29. TPortsLV(
  30. VOID
  31. ) : _bSelectionState( TRUE ),
  32. _bSingleSelection( TRUE ),
  33. _bTwoColumnMode( FALSE ),
  34. _iSelectedItem( -1 ),
  35. _ColumnSortState( kPortHeaderMax ),
  36. _uCurrentColumn( 0 ),
  37. _bAllowSelectionChange( FALSE ),
  38. _bHideFaxPorts( FALSE )
  39. {
  40. vCreatePortDataList();
  41. }
  42. TPortsLV::
  43. ~TPortsLV(
  44. VOID
  45. )
  46. {
  47. vDestroyPortDataList();
  48. }
  49. BOOL
  50. TPortsLV::
  51. bReloadPorts(
  52. IN LPCTSTR pszServerName,
  53. IN BOOL bSelectNewPort
  54. )
  55. /*++
  56. Routine Description:
  57. Read in the remote ports and put them in the listview. If level
  58. 2 fails, we will try 1.
  59. Arguments:
  60. pszServerName - Pointer to server name.
  61. bSelectNewPort - Indicates if a new port is to be located and selected.
  62. TRUE select new port, FALSE do not located new port.
  63. Return Value:
  64. TRUE if ports list loaded, FALSE if error occurred.
  65. --*/
  66. {
  67. TStatusB bStatus( DBG_WARN, ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_LEVEL );
  68. DWORD cbPorts = 0;
  69. PPORT_INFO_2 pPorts = NULL;
  70. DWORD cPorts = 0;
  71. DWORD dwLevel = 2;
  72. //
  73. // Preserve the current check state.
  74. //
  75. TCHAR szPortList[kPortListMax];
  76. vGetPortList( szPortList, COUNTOF( szPortList ) );
  77. //
  78. // Enumerate the port starting at level 2.
  79. //
  80. bStatus DBGCHK = VDataRefresh::bEnumPortsMaxLevel( pszServerName,
  81. &dwLevel,
  82. (PVOID *)&pPorts,
  83. &cbPorts,
  84. &cPorts );
  85. //
  86. // If the ports list cannot be enumerated fail with an error.
  87. //
  88. if( !bStatus ){
  89. DBGMSG( DBG_WARN, ( "PortsLV.bReloadPorts: can't alloc %d %d\n", cbPorts, GetLastError( )));
  90. return FALSE;
  91. }
  92. //
  93. // If option to select newly added port was selected.
  94. //
  95. TString strNewPort;
  96. if( bSelectNewPort ){
  97. //
  98. // Located the newly added port.
  99. //
  100. bSelectNewPort = bLocateAddedPort( strNewPort, pPorts, cPorts, dwLevel );
  101. if( bSelectNewPort ){
  102. DBGMSG( DBG_TRACE, ("New port found " TSTR "\n", (LPCTSTR)strNewPort ) );
  103. }
  104. }
  105. //
  106. // Get the printers
  107. //
  108. PRINTER_INFO_2 *pPrinterInfo2 = NULL;
  109. DWORD cPrinterInfo2 = 0;
  110. DWORD cbPrinterInfo2 = 0;
  111. DWORD dwFlags = PRINTER_ENUM_NAME;
  112. bStatus DBGCHK = VDataRefresh::bEnumPrinters(
  113. dwFlags,
  114. (LPTSTR)pszServerName,
  115. 2,
  116. (PVOID *)&pPrinterInfo2,
  117. &cbPrinterInfo2,
  118. &cPrinterInfo2 );
  119. //
  120. // Delete current ports if they exist.
  121. //
  122. bStatus DBGCHK = ListView_DeleteAllItems( _hwndLV );
  123. //
  124. // Clear the item count.
  125. //
  126. _cLVPorts = 0;
  127. //
  128. // Delete all the port data items.
  129. //
  130. vDestroyPortDataList();
  131. TString strDescription;
  132. //
  133. // Add LPT?: ports
  134. //
  135. strDescription.bLoadString( ghInst, IDS_TEXT_PRINTERPORT );
  136. vInsertPortsByMask(
  137. cPorts,
  138. pPorts,
  139. cPrinterInfo2,
  140. pPrinterInfo2,
  141. dwLevel,
  142. TEXT("lpt?:"),
  143. strDescription
  144. );
  145. //
  146. // Add COM?: ports
  147. //
  148. strDescription.bLoadString( ghInst, IDS_TEXT_SERIALPORT );
  149. vInsertPortsByMask(
  150. cPorts,
  151. pPorts,
  152. cPrinterInfo2,
  153. pPrinterInfo2,
  154. dwLevel,
  155. TEXT("com?:"),
  156. strDescription
  157. );
  158. //
  159. // Add FILE: ports
  160. //
  161. strDescription.bLoadString( ghInst, IDS_TEXT_PRINTTOFILE );
  162. vInsertPortsByMask(
  163. cPorts,
  164. pPorts,
  165. cPrinterInfo2,
  166. pPrinterInfo2,
  167. dwLevel,
  168. TEXT("file:"),
  169. strDescription
  170. );
  171. //
  172. // Add all the rest
  173. //
  174. vInsertPortsByMask(
  175. cPorts,
  176. pPorts,
  177. cPrinterInfo2,
  178. pPrinterInfo2,
  179. dwLevel,
  180. NULL,
  181. NULL
  182. );
  183. //
  184. // Restore the previous check state.
  185. //
  186. vCheckPorts( szPortList );
  187. //
  188. // Select and check the newly added port.
  189. //
  190. if( bSelectNewPort ){
  191. //
  192. // Check off other selected ports
  193. //
  194. INT iItem = -1;
  195. do
  196. {
  197. iItem = ListView_GetNextItem( _hwndLV, iItem, LVNI_SELECTED );
  198. if( iItem != -1 )
  199. {
  200. ListView_SetItemState( _hwndLV,
  201. iItem,
  202. 0,
  203. LVIS_SELECTED | LVIS_FOCUSED );
  204. }
  205. } while( iItem != -1 );
  206. //
  207. // New port is added select and scroll it into view.
  208. //
  209. vItemClicked( iSelectPort( strNewPort ) );
  210. }
  211. //
  212. // This arrays of numbers represents the percentages of
  213. // each column width from the total LV width. The sum
  214. // of all numbers in the array should be equal to 100
  215. // (100% = the total LV width)
  216. //
  217. static UINT arrColW2[] = { 50, 50 };
  218. static UINT arrColW3[] = { 18, 35, 47 };
  219. //
  220. // Adjust columns ...
  221. //
  222. if( !_bTwoColumnMode )
  223. {
  224. vAdjustHeaderColumns( _hwndLV, COUNTOF(arrColW3), arrColW3 );
  225. }
  226. else
  227. {
  228. vAdjustHeaderColumns( _hwndLV, COUNTOF(arrColW2), arrColW2 );
  229. }
  230. //
  231. // Release the enum ports and enum printer memory.
  232. //
  233. FreeMem( pPorts );
  234. FreeMem( pPrinterInfo2 );
  235. return TRUE;
  236. }
  237. BOOL
  238. TPortsLV::
  239. bLocateAddedPort(
  240. IN LPCTSTR pszServerName,
  241. IN TString &strNewPort
  242. )
  243. /*++
  244. Routine Description:
  245. Located the first port which is not in the port list view.
  246. Arguments:
  247. strPort - New port which has been added.
  248. Return Value:
  249. TRUE success, FALSE error occurred.
  250. --*/
  251. {
  252. TStatusB bStatus;
  253. DWORD cbPorts = 0;
  254. PPORT_INFO_2 pPorts = NULL;
  255. DWORD cPorts = 0;
  256. DWORD dwLevel = 2;
  257. //
  258. // Enumerate the port starting at level 2.
  259. //
  260. bStatus DBGCHK = VDataRefresh::bEnumPortsMaxLevel( pszServerName,
  261. &dwLevel,
  262. (PVOID *)&pPorts,
  263. &cbPorts,
  264. &cPorts );
  265. //
  266. // If the ports list cannot be enumerated fail with an error.
  267. //
  268. if( bStatus )
  269. {
  270. //
  271. // Located the newly added port.
  272. //
  273. bStatus DBGCHK = bLocateAddedPort( strNewPort, pPorts, cPorts, dwLevel );
  274. if( bStatus )
  275. {
  276. DBGMSG( DBG_TRACE, ("New port found " TSTR "\n", (LPCTSTR)strNewPort ) );
  277. }
  278. }
  279. //
  280. // Release the port memory.
  281. //
  282. FreeMem( pPorts );
  283. return bStatus;
  284. }
  285. BOOL
  286. TPortsLV::
  287. bLocateAddedPort(
  288. IN OUT TString &strPort,
  289. IN PPORT_INFO_2 pPorts,
  290. IN DWORD cPorts,
  291. IN DWORD dwLevel
  292. )
  293. /*++
  294. Routine Description:
  295. Located the first port which is not in the port list view.
  296. Arguments:
  297. strPort - New port which has been added.
  298. pPorts - Points to a ports enum structure array.
  299. cPorts - Number of elements in the ports enum array.
  300. dwLevel - Level of the ports enum structure array.
  301. Return Value:
  302. TRUE success, FALSE error occurred.
  303. --*/
  304. {
  305. TStatusB bStatus;
  306. LPTSTR pszPort;
  307. bStatus DBGNOCHK = FALSE;
  308. //
  309. // Go through all the ports.
  310. //
  311. for( UINT i=0; i<cPorts; ++i ){
  312. if( dwLevel == 2 ){
  313. //
  314. // If we are to hide the fax ports then
  315. // ignore newly added fax ports.
  316. //
  317. if( _bHideFaxPorts && bIsFaxPort( pPorts[i].pPortName, pPorts[i].pMonitorName ) )
  318. {
  319. DBGMSG( DBG_TRACE, ( "PortsLV.bLocateAddedPort: fax device being skipped.\n" ) );
  320. continue;
  321. }
  322. pszPort = pPorts[i].pPortName;
  323. } else {
  324. pszPort = ((PPORT_INFO_1)pPorts)[i].pName;
  325. }
  326. //
  327. // Look for a portname which is not in the list view.
  328. //
  329. if( iFindPort( pszPort ) < 0 ){
  330. //
  331. // Update the passed in string object.
  332. //
  333. bStatus DBGCHK = strPort.bUpdate( pszPort );
  334. break;
  335. }
  336. }
  337. return bStatus;
  338. }
  339. VOID
  340. TPortsLV::
  341. vSelectPort(
  342. IN LPCTSTR pszPort
  343. )
  344. {
  345. SPLASSERT( pszPort );
  346. iSelectPort( pszPort );
  347. }
  348. VOID
  349. TPortsLV::
  350. vEnable(
  351. IN BOOL bRetainSelection
  352. )
  353. {
  354. if( bRetainSelection )
  355. {
  356. if( _iSelectedItem != -1 )
  357. {
  358. ListView_SetItemState( _hwndLV,
  359. _iSelectedItem,
  360. LVIS_SELECTED | LVIS_FOCUSED,
  361. LVIS_SELECTED | LVIS_FOCUSED );
  362. ListView_EnsureVisible( _hwndLV,
  363. _iSelectedItem,
  364. FALSE );
  365. }
  366. }
  367. EnableWindow( _hwndLV, TRUE );
  368. }
  369. VOID
  370. TPortsLV::
  371. vDisable(
  372. IN BOOL bRetainSelection
  373. )
  374. {
  375. if( bRetainSelection )
  376. {
  377. _iSelectedItem = ListView_GetNextItem( _hwndLV, -1, LVNI_SELECTED );
  378. if( _iSelectedItem != -1 )
  379. {
  380. ListView_SetItemState( _hwndLV,
  381. _iSelectedItem,
  382. 0,
  383. LVIS_SELECTED | LVIS_FOCUSED );
  384. }
  385. }
  386. EnableWindow( _hwndLV, FALSE );
  387. }
  388. VOID
  389. TPortsLV::
  390. vCheckPorts(
  391. IN OUT LPTSTR pszPortString CHANGE
  392. )
  393. /*++
  394. Routine Description:
  395. Set the ports in the listview based on the printers port string.
  396. Arguments:
  397. pszPortName - List of ports, comma delimited. When this is returns,
  398. pszPortName is the same on entry, but it's modified inside this
  399. function.
  400. Return Value:
  401. --*/
  402. {
  403. //
  404. // We will walk though the port string, replacing commas with
  405. // NULLs, but we'll change them back.
  406. //
  407. LPTSTR psz = pszPortString;
  408. SPLASSERT( psz );
  409. LPTSTR pszPort;
  410. INT iItem;
  411. INT iItemFirst = kMaxInt;
  412. while( psz && *psz ){
  413. pszPort = psz;
  414. psz = _tcschr( psz, TEXT( ',' ));
  415. if( psz ){
  416. *psz = 0;
  417. }
  418. iItem = iCheckPort( pszPort );
  419. if( iItem == -1 ){
  420. DBGMSG( DBG_WARN,
  421. ( "PortsLV.vCheckPort: Port "TSTR" not checked.\n", pszPort ));
  422. }
  423. if( iItem < iItemFirst ){
  424. iItemFirst = iItem;
  425. }
  426. if( psz ){
  427. *psz = TEXT( ',' );
  428. ++psz;
  429. }
  430. }
  431. if( iItemFirst == kMaxInt ){
  432. DBGMSG( DBG_PORTSINFO, ( "PortsLV.vCheckPorts: No ports selected.\n" ));
  433. iItemFirst = 0;
  434. }
  435. //
  436. // Select the first item and make sure it is visible.
  437. //
  438. ListView_SetItemState( _hwndLV,
  439. iItemFirst,
  440. LVIS_SELECTED | LVIS_FOCUSED,
  441. LVIS_SELECTED | LVIS_FOCUSED );
  442. ListView_EnsureVisible( _hwndLV,
  443. iItemFirst,
  444. FALSE );
  445. }
  446. VOID
  447. TPortsLV::
  448. vSelectItem(
  449. INT iItem
  450. )
  451. /*++
  452. Routine Description:
  453. Selects an item in the ListView.
  454. Arguments:
  455. iItem - Index of item to select.
  456. Return Value:
  457. --*/
  458. {
  459. ListView_SetItemState( _hwndLV,
  460. iItem,
  461. LVIS_SELECTED,
  462. LVIS_SELECTED );
  463. }
  464. BOOL
  465. TPortsLV::
  466. bSetUI(
  467. IN HWND hwndLV,
  468. IN BOOL bTwoColumnMode,
  469. IN BOOL bSelectionState,
  470. IN BOOL bAllowSelectionChange,
  471. IN HWND hwnd,
  472. IN WPARAM wmDoubleClickMsg,
  473. IN WPARAM wmSingleClickMsg,
  474. IN WPARAM wmDeleteKeyMsg
  475. )
  476. {
  477. _hwndLV = hwndLV;
  478. _bTwoColumnMode = bTwoColumnMode;
  479. _bSelectionState = bSelectionState;
  480. _bAllowSelectionChange = bAllowSelectionChange;
  481. _wmDoubleClickMsg = wmDoubleClickMsg;
  482. _wmSingleClickMsg = wmSingleClickMsg;
  483. _wmDeleteKeyMsg = wmDeleteKeyMsg;
  484. _hwnd = hwnd;
  485. SPLASSERT( _hwndLV );
  486. if( _bSelectionState ){
  487. //
  488. // Add check boxes.
  489. //
  490. HIMAGELIST himlState = ImageList_Create( 16, 16, TRUE, 2, 0 );
  491. //
  492. // !! LATER !!
  493. // Should be created once then shared.
  494. //
  495. if( !himlState ){
  496. DBGMSG( DBG_ERROR, ( "PortsLV.bSetUI: ImageList_Create failed %d\n",
  497. GetLastError( )));
  498. return FALSE;
  499. }
  500. //
  501. // Load the bitmap for the check states.
  502. //
  503. HBITMAP hbm = LoadBitmap( ghInst, MAKEINTRESOURCE( IDB_CHECKSTATES ));
  504. if( !hbm ){
  505. DBGMSG( DBG_ERROR, ( "PortsLV.bSetUI: LoadBitmap failed %d\n",
  506. GetLastError( )));
  507. return FALSE;
  508. }
  509. //
  510. // Add the bitmaps to the image list.
  511. //
  512. ImageList_AddMasked( himlState, hbm, RGB( 255, 0, 0 ));
  513. SendMessage( _hwndLV, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himlState );
  514. DeleteObject( hbm );
  515. }
  516. INT iNumColumns = _bTwoColumnMode ? 2 : kPortHeaderMax;
  517. //
  518. // Initialize the LV_COLUMN structure.
  519. //
  520. LV_COLUMN lvc;
  521. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  522. lvc.fmt = LVCFMT_LEFT;
  523. lvc.cx = kPortHeaderWidthDefault;
  524. RECT rc;
  525. if( !GetClientRect( _hwndLV, &rc )){
  526. DBGMSG( DBG_WARN, ( "PortsLV.bSetUI: GetClientRect failed %d\n", GetLastError( )));
  527. return FALSE;
  528. }
  529. //
  530. // Calculate the column width, less the scroll bar width.
  531. //
  532. lvc.cx = ( ( rc.right - rc.left ) - GetSystemMetrics( SM_CYVSCROLL ) ) / iNumColumns;
  533. TStatusB bStatus;
  534. TString strHeader;
  535. for( INT iCol = 0; iCol < iNumColumns; ++iCol ){
  536. bStatus DBGCHK = strHeader.bLoadString( ghInst, IDS_PHEAD_BEGIN + iCol );
  537. lvc.pszText = (LPTSTR)(LPCTSTR)strHeader;
  538. lvc.iSubItem = iCol;
  539. if( ListView_InsertColumn( _hwndLV, iCol, &lvc ) == -1 ){
  540. DBGMSG( DBG_WARN, ( "PortsLV.bSetUI: LV_Insert failed %d\n", GetLastError( )));
  541. return FALSE;
  542. }
  543. }
  544. //
  545. // Enable full row selection.
  546. //
  547. DWORD dwExStyle = ListView_GetExtendedListViewStyle( _hwndLV );
  548. ListView_SetExtendedListViewStyle( _hwndLV, dwExStyle | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_LABELTIP );
  549. //
  550. // !!LATER!!
  551. // We should read an override flag from the registry.
  552. //
  553. _bHideFaxPorts = TRUE;
  554. return TRUE;
  555. }
  556. VOID
  557. TPortsLV::
  558. vAddPortToListView(
  559. IN LPCTSTR pszName,
  560. IN LPCTSTR pszMonitor,
  561. IN LPCTSTR pszDescription,
  562. IN LPCTSTR pszPrinters
  563. )
  564. {
  565. if( !pszName || !pszName[0] ){
  566. DBGMSG( DBG_WARN,
  567. ( "PortsLV.vAddPortToListView: pszName "TSTR" invalid\n",
  568. DBGSTR( pszName )));
  569. return;
  570. }
  571. //
  572. // If we are to hide the fax ports and this is a fax
  573. // port then just return with out adding the port to
  574. // the list view.
  575. //
  576. if( _bHideFaxPorts && bIsFaxPort( pszName, pszMonitor ) )
  577. {
  578. DBGMSG( DBG_TRACE, ( "PortsLV.vAddPortToListView: fax device being removed.\n" ) );
  579. return;
  580. }
  581. //
  582. // Add this port to the port data list.
  583. //
  584. TPortData *pPortData = AddPortDataList( pszName, pszMonitor, pszDescription, pszPrinters );
  585. LV_ITEM lvi;
  586. if( _bSelectionState ){
  587. lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
  588. } else {
  589. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  590. }
  591. lvi.state = kStateUnchecked;
  592. lvi.pszText = (LPTSTR)pszName;
  593. lvi.iItem = _cLVPorts;
  594. lvi.iSubItem = 0;
  595. lvi.lParam = (LPARAM)pPortData;
  596. ListView_InsertItem( _hwndLV, &lvi );
  597. ListView_SetItemText( _hwndLV, _cLVPorts, 1, (LPTSTR)pszDescription );
  598. if( !_bTwoColumnMode )
  599. {
  600. ListView_SetItemText( _hwndLV, _cLVPorts, 2, (LPTSTR)pszPrinters );
  601. }
  602. ++_cLVPorts;
  603. }
  604. VOID
  605. TPortsLV::
  606. vDeletePortFromListView(
  607. IN LPCTSTR pszName
  608. )
  609. {
  610. //
  611. // Locate the port in the list view.
  612. //
  613. INT iItem = iFindPort ( pszName );
  614. if( iItem != -1 ){
  615. //
  616. // Delete this port from the port data list.
  617. //
  618. DeletePortDataList( pszName );
  619. ListView_DeleteItem( _hwndLV, iItem );
  620. //
  621. // Select next item. If the item we just deleted is the last item,
  622. // we need to select the previous one.
  623. //
  624. // If we deleted the last item, leave it as is.
  625. //
  626. if( ListView_GetItemCount( _hwndLV ) == iItem &&
  627. iItem > 0 ) {
  628. --iItem;
  629. }
  630. ListView_SetItemState( _hwndLV,
  631. iItem,
  632. LVIS_SELECTED | LVIS_FOCUSED,
  633. LVIS_SELECTED | LVIS_FOCUSED );
  634. }
  635. }
  636. INT
  637. TPortsLV::
  638. iFindPort(
  639. IN LPCTSTR pszPort
  640. )
  641. /*++
  642. Routine Description:
  643. Located the specified port name in the list view.
  644. Arguments:
  645. pszPort - Port name to locate.
  646. Return Value:
  647. iItem id if found, -1 if item was not found.
  648. --*/
  649. {
  650. SPLASSERT( pszPort );
  651. LV_FINDINFO lvfi;
  652. lvfi.flags = LVFI_STRING;
  653. lvfi.psz = pszPort;
  654. INT iItem = ListView_FindItem( _hwndLV, -1, &lvfi );
  655. if( iItem == -1 ){
  656. DBGMSG( DBG_WARN, ( "PortsLV.iFindPort: port "TSTR" not found\n", pszPort ));
  657. }
  658. return iItem;
  659. }
  660. INT
  661. TPortsLV::
  662. iCheckPort(
  663. IN LPCTSTR pszPort
  664. )
  665. /*++
  666. Routine Description:
  667. Places the check mark next to a port in the list view.
  668. Arguments:
  669. pszPort - Port to check.
  670. Return Value:
  671. iItem checked, -1 == error.
  672. --*/
  673. {
  674. //
  675. // Locate the port in the list view.
  676. //
  677. INT iItem = iFindPort ( pszPort );
  678. if( iItem != -1 ){
  679. //
  680. // Set the item selection state.
  681. //
  682. ListView_SetItemState( _hwndLV,
  683. iItem,
  684. kStateChecked,
  685. kStateMask );
  686. //
  687. // Try and make as many ports visible as possible.
  688. //
  689. ListView_EnsureVisible( _hwndLV,
  690. iItem,
  691. FALSE );
  692. }
  693. return iItem;
  694. }
  695. INT
  696. TPortsLV::
  697. iSelectPort(
  698. IN LPCTSTR pszPort
  699. )
  700. /*++
  701. Routine Description:
  702. Select the port in the list view.
  703. Arguments:
  704. pszPort - Port to check.
  705. Return Value:
  706. iItem checked, -1 == error.
  707. --*/
  708. {
  709. //
  710. // Locate the port in the list view.
  711. //
  712. INT iItem = iFindPort ( pszPort );
  713. if( iItem != -1 ){
  714. //
  715. // Select the port specified by pszPort.
  716. //
  717. ListView_SetItemState( _hwndLV,
  718. iItem,
  719. LVIS_SELECTED | LVIS_FOCUSED,
  720. LVIS_SELECTED | LVIS_FOCUSED );
  721. //
  722. // Try and make as many ports visible as possible.
  723. //
  724. ListView_EnsureVisible( _hwndLV,
  725. iItem,
  726. FALSE );
  727. }
  728. return iItem;
  729. }
  730. VOID
  731. TPortsLV::
  732. vGetPortList(
  733. OUT LPTSTR pszPortList,
  734. IN COUNT cchPortList
  735. )
  736. {
  737. INT cPorts = 0;
  738. DWORD i;
  739. LV_ITEM lvi;
  740. LPTSTR pszPort = pszPortList;
  741. DWORD cchSpaceLeft = cchPortList - 1;
  742. DWORD cchLen;
  743. lvi.iSubItem = 0;
  744. DWORD cItems = ListView_GetItemCount( _hwndLV );
  745. for( pszPortList[0] = 0, i=0; i<cItems; ++i ){
  746. if( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked ){
  747. lvi.pszText = pszPort;
  748. lvi.cchTextMax = cchSpaceLeft;
  749. cchLen = (DWORD)SendMessage( _hwndLV,
  750. LVM_GETITEMTEXT,
  751. (WPARAM)i,
  752. (LPARAM)&lvi );
  753. if( cchLen + 1 > cchSpaceLeft ){
  754. DBGMSG( DBG_WARN, ( "PortsLV.iGetPorts: Out of string space!\n" ));
  755. return;
  756. }
  757. pszPort += cchLen;
  758. cchSpaceLeft -= cchLen+1;
  759. *pszPort = TEXT( ',' );
  760. ++pszPort;
  761. ++cPorts;
  762. }
  763. }
  764. //
  765. // If we had any ports, back up to remove the last comma.
  766. //
  767. if( cPorts ){
  768. --pszPort;
  769. }
  770. //
  771. // Null terminate.
  772. //
  773. *pszPort = 0;
  774. }
  775. BOOL
  776. TPortsLV::
  777. bReadUI(
  778. OUT TString &strPortString,
  779. IN BOOL bSelectedPort
  780. )
  781. {
  782. TCHAR szPortList[kPortListMax];
  783. szPortList[0] = 0;
  784. //
  785. // If we are in single select mode just return
  786. // the selected port.
  787. //
  788. if( bSelectedPort )
  789. {
  790. (VOID)bGetSelectedPort( szPortList, COUNTOF( szPortList ) );
  791. }
  792. else
  793. {
  794. //
  795. // Get the list of check ports from the list view.
  796. //
  797. vGetPortList( szPortList, COUNTOF( szPortList ) );
  798. }
  799. //
  800. // Update the port list.
  801. //
  802. return strPortString.bUpdate( szPortList );
  803. }
  804. VOID
  805. TPortsLV::
  806. vItemClicked(
  807. IN INT iItem
  808. )
  809. /*++
  810. Routine Description:
  811. User clicked in listview. Check if item state should
  812. be changed.
  813. The item will also be selected.
  814. Arguments:
  815. iItem - Item that has been clicked.
  816. Return Value:
  817. --*/
  818. {
  819. if( iItem == -1 ){
  820. DBGMSG( DBG_WARN, ( "PortsLV.vItemClicked: -1 passed in\n" ));
  821. return;
  822. }
  823. //
  824. // If in single selection mode clear all items checked and only
  825. // check the specified item.
  826. //
  827. if( _bSingleSelection ){
  828. DWORD cItems = ListView_GetItemCount( _hwndLV );
  829. for( UINT i=0; i<cItems; ++i ){
  830. if( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked ){
  831. if( iItem == (INT)i ){
  832. continue;
  833. } else {
  834. ListView_SetItemState( _hwndLV,
  835. i,
  836. kStateUnchecked,
  837. kStateMask );
  838. }
  839. }
  840. }
  841. }
  842. //
  843. // Retrieve the old state, toggle it, then set it.
  844. //
  845. DWORD dwState = ListView_GetItemState( _hwndLV,
  846. iItem,
  847. kStateMask );
  848. //
  849. // When we are in single select mode we want to always check
  850. // the currently selected item.
  851. //
  852. if( !_bSingleSelection )
  853. {
  854. dwState = ( dwState == kStateChecked ) ?
  855. kStateUnchecked | LVIS_SELECTED | LVIS_FOCUSED :
  856. kStateChecked | LVIS_SELECTED | LVIS_FOCUSED;
  857. }
  858. else
  859. {
  860. dwState = kStateChecked | LVIS_SELECTED | LVIS_FOCUSED;
  861. }
  862. //
  863. // Set the new item state.
  864. //
  865. ListView_SetItemState( _hwndLV,
  866. iItem,
  867. dwState,
  868. kStateMask | LVIS_SELECTED | LVIS_FOCUSED );
  869. }
  870. COUNT
  871. TPortsLV::
  872. cSelectedPorts(
  873. VOID
  874. )
  875. /*++
  876. Routine Description:
  877. Returns the number of items which have a check mark
  878. next to them.
  879. Arguments:
  880. None.
  881. Return Value:
  882. Return the number of checked items.
  883. --*/
  884. {
  885. DWORD cItems = ListView_GetItemCount( _hwndLV );
  886. COUNT cItemsSelected = 0;
  887. DWORD i;
  888. for( i = 0; i < cItems; ++i )
  889. {
  890. if( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked )
  891. {
  892. ++cItemsSelected;
  893. }
  894. }
  895. return cItemsSelected;
  896. }
  897. COUNT
  898. TPortsLV::
  899. cSelectedItems(
  900. VOID
  901. )
  902. /*++
  903. Routine Description:
  904. Returns the number of items which are currently selected.
  905. Arguments:
  906. None.
  907. Return Value:
  908. Return the number of selected items.
  909. --*/
  910. {
  911. DWORD cItems = ListView_GetItemCount( _hwndLV );
  912. COUNT cItemsSelected = 0;
  913. DWORD i;
  914. for( i = 0; i < cItems; ++i )
  915. {
  916. if( ListView_GetItemState( _hwndLV, i, LVIS_SELECTED ) & LVIS_SELECTED )
  917. {
  918. ++cItemsSelected;
  919. }
  920. }
  921. return cItemsSelected;
  922. }
  923. VOID
  924. TPortsLV::
  925. vRemoveAllChecks(
  926. VOID
  927. )
  928. /*++
  929. Routine Description:
  930. Removes all the check marks for the list view.
  931. Arguments:
  932. None.
  933. Return Value:
  934. Nothing.
  935. --*/
  936. {
  937. DWORD cItems = ListView_GetItemCount( _hwndLV );
  938. COUNT cItemsSelected = 0;
  939. DWORD i;
  940. for( i=0; i<cItems; ++i ){
  941. if( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked ){
  942. ListView_SetItemState( _hwndLV,
  943. i,
  944. kStateUnchecked,
  945. kStateMask );
  946. }
  947. }
  948. }
  949. VOID
  950. TPortsLV::
  951. vSetFocus(
  952. VOID
  953. )
  954. {
  955. SetFocus( _hwndLV );
  956. }
  957. BOOL
  958. TPortsLV::
  959. bGetSelectedPort(
  960. OUT LPTSTR pszPort,
  961. IN COUNT cchPort
  962. )
  963. /*++
  964. Routine Description:
  965. Retrieve the currently selected port in the list view.
  966. Arguments:
  967. pszPort - TCHAR array to receive port
  968. cchPort - COUNTOF port string.
  969. Return Value:
  970. TRUE - success, FALSE = fail.
  971. --*/
  972. {
  973. INT iItem = ListView_GetNextItem( _hwndLV,
  974. -1,
  975. LVNI_SELECTED );
  976. if( iItem == -1 ){
  977. DBGMSG( DBG_WARN,
  978. ( "PrinterPort.bGetSelectedPort: Unable to retrieve next selected item %d\n",
  979. GetLastError( )));
  980. return FALSE;
  981. }
  982. ListView_GetItemText( _hwndLV,
  983. iItem,
  984. 0,
  985. pszPort,
  986. cchPort );
  987. return TRUE;
  988. }
  989. BOOL
  990. TPortsLV::
  991. bGetSelectedPort(
  992. OUT LPTSTR pszPort,
  993. IN COUNT cchPort,
  994. INT *pItem
  995. )
  996. /*++
  997. Routine Description:
  998. Retrieve the currently selected port in the list view.
  999. Arguments:
  1000. pszPort - TCHAR array to receive port
  1001. cchPort - COUNTOF port string.
  1002. iItem - Index of the item with which to begin the search
  1003. Return Value:
  1004. TRUE - success, FALSE = fail.
  1005. iItem will be set to the new found index.
  1006. --*/
  1007. {
  1008. INT iItem = *pItem;
  1009. iItem = ListView_GetNextItem( _hwndLV,
  1010. iItem,
  1011. LVNI_SELECTED );
  1012. if( iItem == -1 ){
  1013. DBGMSG( DBG_WARN,
  1014. ( "PrinterPort.bGetSelectedPort: Unable to retrieve next selected item %d\n",
  1015. GetLastError( )));
  1016. return FALSE;
  1017. }
  1018. ListView_GetItemText( _hwndLV,
  1019. iItem,
  1020. 0,
  1021. pszPort,
  1022. cchPort );
  1023. *pItem = iItem;
  1024. return TRUE;
  1025. }
  1026. BOOL
  1027. TPortsLV::
  1028. bHandleNotifyMessage(
  1029. LPARAM lParam
  1030. )
  1031. {
  1032. BOOL bStatus = TRUE;
  1033. LPNMHDR pnmh = (LPNMHDR)lParam;
  1034. switch( pnmh->code )
  1035. {
  1036. case NM_DBLCLK:
  1037. vHandleItemClicked( lParam );
  1038. if( _wmDoubleClickMsg )
  1039. {
  1040. PostMessage( _hwnd, WM_COMMAND, _wmDoubleClickMsg, 0 );
  1041. }
  1042. break;
  1043. case NM_CLICK:
  1044. vHandleItemClicked( lParam );
  1045. if( _wmSingleClickMsg )
  1046. {
  1047. PostMessage( _hwnd, WM_COMMAND, _wmSingleClickMsg, 0 );
  1048. }
  1049. break;
  1050. case LVN_KEYDOWN:
  1051. {
  1052. LV_KEYDOWN* plvnkd = (LV_KEYDOWN *)lParam;
  1053. if( _bSelectionState && _bAllowSelectionChange )
  1054. {
  1055. //
  1056. // !! LATER !!
  1057. //
  1058. // Is this the best way to check whether the ALT
  1059. // key is _not_ down?
  1060. //
  1061. if( plvnkd->wVKey == TEXT( ' ' ) &&
  1062. !( GetKeyState( VK_LMENU ) & 0x80000000 ) &&
  1063. !( GetKeyState( VK_RMENU ) & 0x80000000 ))
  1064. {
  1065. vItemClicked( ListView_GetNextItem( _hwndLV, -1, LVNI_SELECTED ));
  1066. }
  1067. }
  1068. //
  1069. // If the delete key was used then post a message to
  1070. // appropriate window with the specified message.
  1071. //
  1072. if(plvnkd->wVKey == VK_DELETE )
  1073. {
  1074. if( _wmDeleteKeyMsg )
  1075. {
  1076. PostMessage( _hwnd, WM_COMMAND, _wmDeleteKeyMsg, 0 );
  1077. }
  1078. }
  1079. }
  1080. break;
  1081. case LVN_COLUMNCLICK:
  1082. {
  1083. NM_LISTVIEW *pNm = (NM_LISTVIEW *)lParam;
  1084. (VOID)bListViewSort( pNm->iSubItem );
  1085. }
  1086. break;
  1087. default:
  1088. bStatus = FALSE;
  1089. break;
  1090. }
  1091. return bStatus;
  1092. }
  1093. VOID
  1094. TPortsLV::
  1095. vHandleItemClicked(
  1096. IN LPARAM lParam
  1097. )
  1098. {
  1099. if( _bSelectionState && _bAllowSelectionChange )
  1100. {
  1101. LV_HITTESTINFO lvhti;
  1102. DWORD dwPos = GetMessagePos();
  1103. POINTS &pt = MAKEPOINTS(dwPos);
  1104. lvhti.pt.x = pt.x;
  1105. lvhti.pt.y = pt.y;
  1106. MapWindowPoints( HWND_DESKTOP, _hwndLV, &lvhti.pt, 1 );
  1107. INT iItem = ListView_HitTest( _hwndLV, &lvhti );
  1108. if( iItem != -1 )
  1109. {
  1110. vItemClicked( iItem );
  1111. }
  1112. }
  1113. }
  1114. VOID
  1115. TPortsLV::
  1116. vInsertPortsByMask(
  1117. IN UINT cPorts,
  1118. IN PORT_INFO_2 pPorts[],
  1119. IN UINT cPrinters,
  1120. IN PRINTER_INFO_2 pPrinters[],
  1121. IN DWORD dwLevel,
  1122. IN LPCTSTR pszTemplate,
  1123. IN LPCTSTR pszDescription
  1124. )
  1125. {
  1126. TString strPrinters;
  1127. //
  1128. // Go through the ports and add them.
  1129. //
  1130. for( UINT i=0; i<cPorts; ++i )
  1131. {
  1132. if( dwLevel == 2 )
  1133. {
  1134. //
  1135. // Check if this port has been added
  1136. //
  1137. if( NULL == pPorts[i].pPortName )
  1138. {
  1139. continue;
  1140. }
  1141. //
  1142. // Check if the port name matches the template
  1143. //
  1144. if( pszTemplate && !bMatchTemplate( pszTemplate, pPorts[i].pPortName ) )
  1145. {
  1146. continue;
  1147. }
  1148. //
  1149. // Assign proper description
  1150. //
  1151. LPCTSTR pszDescr = pszDescription;
  1152. if( !pszDescr )
  1153. {
  1154. pszDescr = pPorts[i].pDescription;
  1155. }
  1156. //
  1157. // If we have printers on this machine.
  1158. //
  1159. if( pPrinters && cPrinters )
  1160. {
  1161. vPrintersUsingPort( strPrinters, pPrinters, cPrinters, pPorts[i].pPortName );
  1162. }
  1163. vAddPortToListView( pPorts[i].pPortName, pPorts[i].pMonitorName, pszDescr, strPrinters );
  1164. //
  1165. // Mark the port as added
  1166. //
  1167. pPorts[i].pPortName = NULL;
  1168. }
  1169. else
  1170. {
  1171. //
  1172. // Check if this port has been added
  1173. //
  1174. if( NULL == ((PPORT_INFO_1)pPorts)[i].pName )
  1175. {
  1176. continue;
  1177. }
  1178. //
  1179. // Check if the port name matches the template
  1180. //
  1181. if( pszTemplate && !bMatchTemplate( pszTemplate, ((PPORT_INFO_1)pPorts)[i].pName ) )
  1182. {
  1183. continue;
  1184. }
  1185. //
  1186. // If we have printers on this machine.
  1187. //
  1188. if( pPrinters && cPrinters )
  1189. {
  1190. vPrintersUsingPort( strPrinters, pPrinters, cPrinters, ((PPORT_INFO_1)pPorts)[i].pName );
  1191. }
  1192. vAddPortToListView( ((PPORT_INFO_1)pPorts)[i].pName, gszNULL, gszNULL, strPrinters );
  1193. //
  1194. // Mark the port as added
  1195. //
  1196. ((PPORT_INFO_1)pPorts)[i].pName = NULL;
  1197. }
  1198. }
  1199. }
  1200. BOOL
  1201. TPortsLV::
  1202. bDeletePorts(
  1203. IN HWND hDlg,
  1204. IN LPCTSTR pszServer
  1205. )
  1206. /*++
  1207. Routine Description:
  1208. Delete selected ports for given print server.
  1209. Arguments:
  1210. hDlg - dialog handle for port tab.
  1211. pszServer - print server name.
  1212. Return Value:
  1213. True if at least one port is deleted, false otherwise.
  1214. --*/
  1215. {
  1216. TStatusB bStatus;
  1217. TCHAR szPortName[TPortsLV::kPortNameMax];
  1218. COUNT cItems;
  1219. INT iItem = -1;
  1220. INT i;
  1221. BOOL bFailed = FALSE;
  1222. BOOL bDeleted = FALSE;
  1223. //
  1224. // Check whether multi ports are selected
  1225. //
  1226. cItems = cSelectedItems();
  1227. if(cItems == 0)
  1228. {
  1229. return FALSE;
  1230. }
  1231. //
  1232. // Get the first selected port name to compose the warning message
  1233. //
  1234. bStatus DBGCHK = bGetSelectedPort( szPortName, COUNTOF( szPortName ) );
  1235. if( IDYES == iMessage( hDlg,
  1236. IDS_DELETE_PORT_TITLE,
  1237. cItems > 1 ? IDS_DELETE_PORTN : IDS_DELETE_PORT,
  1238. MB_YESNO | MB_ICONQUESTION,
  1239. kMsgNone,
  1240. NULL,
  1241. szPortName ))
  1242. {
  1243. //
  1244. // Try to delete all selected items
  1245. //
  1246. for( i = 0; i < (INT)cItems ; i++ )
  1247. {
  1248. //
  1249. // Get each selected port name
  1250. //
  1251. bStatus DBGCHK = bGetSelectedPort( szPortName, COUNTOF( szPortName ), &iItem );
  1252. SPLASSERT( bStatus );
  1253. SPLASSERT( iItem != -1 );
  1254. //
  1255. // Attempt to delete the selected port.
  1256. //
  1257. bStatus DBGCHK = DeletePort( (LPTSTR)pszServer, hDlg, szPortName );
  1258. if( bStatus )
  1259. {
  1260. //
  1261. // Succeeded, refresh the ports UI by deleting the port.
  1262. //
  1263. vDeletePortFromListView( szPortName );
  1264. //
  1265. // Decrease the iItem because deleting one item in the list
  1266. //
  1267. iItem--;
  1268. bDeleted = TRUE;
  1269. }
  1270. else
  1271. {
  1272. if( GetLastError() != ERROR_CANCELLED )
  1273. {
  1274. bFailed = TRUE;
  1275. }
  1276. }
  1277. }
  1278. //
  1279. // Only show an error message if the did not cancel the
  1280. // the action.
  1281. //
  1282. if( bFailed )
  1283. {
  1284. iMessage( hDlg,
  1285. IDS_DELETE_PORT_TITLE,
  1286. cItems > 1 ? IDS_ERR_DELETE_PORTN : IDS_ERR_DELETE_PORT,
  1287. MB_OK | MB_ICONEXCLAMATION,
  1288. kMsgGetLastError,
  1289. gaMsgErrMapPorts);
  1290. }
  1291. bStatus DBGNOCHK = bDeleted;
  1292. }
  1293. else
  1294. {
  1295. bStatus DBGNOCHK = FALSE;
  1296. }
  1297. return bStatus;
  1298. }
  1299. BOOL
  1300. TPortsLV::
  1301. bConfigurePort(
  1302. IN HWND hDlg,
  1303. IN LPCTSTR pszServer
  1304. )
  1305. {
  1306. static MSG_ERRMAP aMsgErrMapPorts[] = {
  1307. ERROR_INVALID_PARAMETER, IDS_ERR_PORT_DOES_NOT_EXIST,
  1308. 0, 0
  1309. };
  1310. TStatusB bStatus;
  1311. TCHAR szPortName[TPortsLV::kPortNameMax];
  1312. bStatus DBGCHK = bGetSelectedPort( szPortName, COUNTOF( szPortName ) );
  1313. if( bStatus )
  1314. {
  1315. bStatus DBGCHK = ConfigurePort( (LPTSTR)pszServer,
  1316. hDlg,
  1317. szPortName );
  1318. if( !bStatus )
  1319. {
  1320. if( GetLastError() != ERROR_CANCELLED )
  1321. {
  1322. iMessage( hDlg,
  1323. IDS_CONFIGURE_PORT_TITLE,
  1324. IDS_ERR_CONFIG_PORT,
  1325. MB_OK | MB_ICONEXCLAMATION,
  1326. kMsgGetLastError,
  1327. aMsgErrMapPorts );
  1328. }
  1329. }
  1330. }
  1331. else
  1332. {
  1333. DBGMSG( DBG_WARN, ( "PrinterPorts.vConfigure: failed %d\n", GetLastError( )));
  1334. }
  1335. return bStatus;
  1336. }
  1337. VOID
  1338. TPortsLV::
  1339. vPrintersUsingPort(
  1340. IN OUT TString &strPrinters,
  1341. IN PRINTER_INFO_2 *pPrinterInfo,
  1342. IN DWORD cPrinterInfo,
  1343. IN LPCTSTR pszPortName
  1344. )
  1345. /*++
  1346. Routine Description:
  1347. Builds a comma separated string of all the printers
  1348. using the specified port.
  1349. Arguments:
  1350. strPrinters - TString refrence where to return resultant string.
  1351. pPrinterInfo - Pointer to a printer info level 2 structure array.
  1352. cPrinterInfo - Number of printers in the printer info 2 array.
  1353. pszPortName - Pointer to string or port name to match.
  1354. Return Value:
  1355. Nothing.
  1356. Notes:
  1357. If no printer is using the specfied port the string refrence
  1358. will contain an empty string.
  1359. --*/
  1360. {
  1361. SPLASSERT( pPrinterInfo );
  1362. SPLASSERT( pszPortName );
  1363. LPTSTR psz;
  1364. LPTSTR pszPort;
  1365. LPTSTR pszPrinter;
  1366. UINT i;
  1367. //
  1368. // Clear the current printer buffer.
  1369. //
  1370. TStatusB bStatus;
  1371. bStatus DBGCHK = strPrinters.bUpdate( NULL );
  1372. //
  1373. // Traverse the printer info array.
  1374. //
  1375. for( i = 0; i < cPrinterInfo; i++ ){
  1376. for( psz = pPrinterInfo[i].pPortName; psz && *psz; ){
  1377. //
  1378. // Look for a comma if found terminate the port string.
  1379. //
  1380. pszPort = psz;
  1381. psz = _tcschr( psz, TEXT( ',' ) );
  1382. if( psz ){
  1383. *psz = 0;
  1384. }
  1385. //
  1386. // Check for a port match.
  1387. //
  1388. if( !_tcsicmp( pszPort, pszPortName ) ){
  1389. //
  1390. // Point to printer name.
  1391. //
  1392. pszPrinter = pPrinterInfo[i].pPrinterName;
  1393. //
  1394. // Strip the server name here.
  1395. //
  1396. if( pPrinterInfo[i].pPrinterName[0] == TEXT( '\\' ) &&
  1397. pPrinterInfo[i].pPrinterName[1] == TEXT( '\\' ) ){
  1398. //
  1399. // Locate the printer name.
  1400. //
  1401. pszPrinter = _tcschr( pPrinterInfo[i].pPrinterName+2, TEXT( '\\' ) );
  1402. pszPrinter = pszPrinter ? pszPrinter+1 : pPrinterInfo[i].pPrinterName;
  1403. }
  1404. //
  1405. // If this is the first time do not place a comma separator.
  1406. //
  1407. if( !strPrinters.bEmpty() ){
  1408. bStatus DBGCHK = strPrinters.bCat( TEXT( ", " ) );
  1409. if( !bStatus ){
  1410. DBGMSG( DBG_WARN, ( "Error cat string line: %d file : %s.\n", __LINE__, __FILE__ ) );
  1411. break;
  1412. }
  1413. }
  1414. //
  1415. // Tack on the printer name
  1416. //
  1417. bStatus DBGCHK = strPrinters.bCat( pszPrinter );
  1418. if( !bStatus ){
  1419. DBGMSG( DBG_WARN, ( "Error cat string line : %d file : %s.\n", __LINE__, __FILE__ ) );
  1420. break;
  1421. }
  1422. }
  1423. //
  1424. // Replace the previous comma.
  1425. //
  1426. if( psz ){
  1427. *psz = TEXT( ',' );
  1428. ++psz;
  1429. }
  1430. }
  1431. }
  1432. }
  1433. VOID
  1434. TPortsLV::
  1435. vSetSingleSelection(
  1436. IN BOOL bSingleSelection
  1437. )
  1438. /*++
  1439. Routine Description:
  1440. Set the list view into single selection mode.
  1441. Arguments:
  1442. bSingleSelection - TRUE single selection, FALSE multi selection.
  1443. Return Value:
  1444. Nothing.
  1445. --*/
  1446. {
  1447. _bSingleSelection = bSingleSelection;
  1448. }
  1449. BOOL
  1450. TPortsLV::
  1451. bGetSingleSelection(
  1452. VOID
  1453. )
  1454. /*++
  1455. Routine Description:
  1456. Get the current list view selection mode.
  1457. Arguments:
  1458. None.
  1459. Return Value:
  1460. TURE in single selection mode, FALSE in multi selection mode.
  1461. --*/
  1462. {
  1463. return _bSingleSelection;
  1464. }
  1465. VOID
  1466. TPortsLV::
  1467. vCreatePortDataList(
  1468. VOID
  1469. )
  1470. /*++
  1471. Routine Description:
  1472. Initialize the port data list.
  1473. Arguments:
  1474. None.
  1475. Return Value:
  1476. Nothing.
  1477. --*/
  1478. {
  1479. DBGMSG( DBG_TRACE, ( "PortsLV::vCreatePortDataList\n" ) );
  1480. PortDataList_vReset();
  1481. }
  1482. VOID
  1483. TPortsLV::
  1484. vDestroyPortDataList(
  1485. VOID
  1486. )
  1487. /*++
  1488. Routine Description:
  1489. Destroy the port data list.
  1490. Arguments:
  1491. None.
  1492. Return Value:
  1493. Nothing.
  1494. --*/
  1495. {
  1496. DBGMSG( DBG_TRACE, ( "PortsLV::vDestroyPortDataList\n" ) );
  1497. TIter Iter;
  1498. TPortData *pPortData;
  1499. for( PortDataList_vIterInit( Iter ), Iter.vNext(); Iter.bValid(); )
  1500. {
  1501. pPortData = PortDataList_pConvert( Iter );
  1502. Iter.vNext();
  1503. delete pPortData;
  1504. }
  1505. }
  1506. BOOL
  1507. TPortsLV::
  1508. bListViewSort(
  1509. IN UINT uColumn
  1510. )
  1511. /*++
  1512. Routine Description:
  1513. This function is called to sort the items. The current
  1514. column indes is specified to indicated witch column to
  1515. sort.
  1516. Arguments:
  1517. Column index to sort.
  1518. Return Value:
  1519. TRUE list is sorted, FALSE error occurred.
  1520. --*/
  1521. {
  1522. DBGMSG( DBG_TRACE, ( "PortsLV::bListViewSort Column %d\n", uColumn ) );
  1523. //
  1524. // Set the surrent column number.
  1525. //
  1526. _uCurrentColumn = uColumn;
  1527. //
  1528. // Tell the list view to sort.
  1529. //
  1530. TStatusB bStatus;
  1531. bStatus DBGCHK = ListView_SortItems( _hwndLV, iCompareProc, (LPARAM)this );
  1532. //
  1533. // Toggle the specified column sort state.
  1534. //
  1535. _ColumnSortState.bToggle( uColumn );
  1536. return bStatus;
  1537. }
  1538. INT
  1539. CALLBACK
  1540. TPortsLV::
  1541. iCompareProc(
  1542. IN LPARAM lParam1,
  1543. IN LPARAM lParam2,
  1544. IN LPARAM RefData
  1545. )
  1546. /*++
  1547. Routine Description:
  1548. List view defined compare routine.
  1549. Arguments:
  1550. None.
  1551. Return Value:
  1552. Nothing.
  1553. --*/
  1554. {
  1555. TPortData *pPortData1 = reinterpret_cast<TPortData *>( lParam1 );
  1556. TPortData *pPortData2 = reinterpret_cast<TPortData *>( lParam2 );
  1557. TPortsLV *pPortsLV = reinterpret_cast<TPortsLV *>( RefData );
  1558. INT iResult = 0;
  1559. LPCTSTR strName1 = NULL;
  1560. LPCTSTR strName2 = NULL;
  1561. if( pPortsLV && pPortData1 && pPortData2 )
  1562. {
  1563. BOOL bStatus = TRUE;
  1564. switch( pPortsLV->_uCurrentColumn )
  1565. {
  1566. case 0:
  1567. strName1 = pPortData1->_strName;
  1568. strName2 = pPortData2->_strName;
  1569. break;
  1570. case 1:
  1571. strName1 = pPortData1->_strDescription;
  1572. strName2 = pPortData2->_strDescription;
  1573. break;
  1574. case 2:
  1575. strName1 = pPortData1->_strPrinters;
  1576. strName2 = pPortData2->_strPrinters;
  1577. break;
  1578. default:
  1579. bStatus = FALSE;
  1580. break;
  1581. }
  1582. if( bStatus )
  1583. {
  1584. if( pPortsLV->_ColumnSortState.bRead( pPortsLV->_uCurrentColumn ) )
  1585. iResult = _tcsicmp( strName2, strName1 );
  1586. else
  1587. iResult = _tcsicmp( strName1, strName2 );
  1588. }
  1589. }
  1590. return iResult;
  1591. }
  1592. TPortsLV::TPortData *
  1593. TPortsLV::
  1594. AddPortDataList(
  1595. IN LPCTSTR pszName,
  1596. IN LPCTSTR pszMonitor,
  1597. IN LPCTSTR pszDescription,
  1598. IN LPCTSTR pszPrinters
  1599. )
  1600. /*++
  1601. Routine Description:
  1602. Add port to port data list.
  1603. Arguments:
  1604. pszName - pointer to port name.
  1605. pszDescription - pointer to description string.
  1606. pszPrinters - pointer to printers using this port string.
  1607. Return Value:
  1608. TRUE port added to data list, FALSE error occurred.
  1609. --*/
  1610. {
  1611. DBGMSG( DBG_TRACE, ( "PortsLV::AddPortDataList\n" ) );
  1612. //
  1613. // Allocate the port data.
  1614. //
  1615. TPortData *pPortData = new TPortData( pszName, pszMonitor, pszDescription, pszPrinters );
  1616. //
  1617. // If valid object created.
  1618. //
  1619. if( VALID_PTR( pPortData ) )
  1620. {
  1621. //
  1622. // Add the port data to the list.
  1623. //
  1624. PortDataList_vAppend( pPortData );
  1625. }
  1626. else
  1627. {
  1628. //
  1629. // The object may have been allocated, however failed construction.
  1630. //
  1631. delete pPortData;
  1632. pPortData = NULL;
  1633. }
  1634. return pPortData;
  1635. }
  1636. BOOL
  1637. TPortsLV::
  1638. DeletePortDataList(
  1639. IN LPCTSTR pszName
  1640. )
  1641. /*++
  1642. Routine Description:
  1643. Delete the specified port from the port data list.
  1644. Arguments:
  1645. pszName - pointer to port name.
  1646. Return Value:
  1647. TRUE port delete, FALSE error occurred.
  1648. --*/
  1649. {
  1650. DBGMSG( DBG_TRACE, ( "PortsLV::DeletePortDataList\n" ) );
  1651. BOOL bStatus = FALSE;
  1652. TIter Iter;
  1653. for( PortDataList_vIterInit( Iter ), Iter.vNext(); Iter.bValid(); Iter.vNext() )
  1654. {
  1655. TPortData *pPortData = PortDataList_pConvert( Iter );
  1656. if( pPortData->_strName == pszName )
  1657. {
  1658. DBGMSG( DBG_TRACE, ( "PortsLV::DeletePortDataList Port "TSTR" deleted\n", pszName ) );
  1659. delete pPortData;
  1660. bStatus = TRUE;
  1661. break;
  1662. }
  1663. }
  1664. return bStatus;
  1665. }
  1666. /********************************************************************
  1667. Port Data helper class.
  1668. ********************************************************************/
  1669. TPortsLV::TPortData::
  1670. TPortData(
  1671. IN LPCTSTR pszName,
  1672. IN LPCTSTR pszMonitor,
  1673. IN LPCTSTR pszDescription,
  1674. IN LPCTSTR pszPrinters
  1675. )
  1676. {
  1677. DBGMSG( DBG_TRACE, ( "PortsLV::TPortData ctor\n" ) );
  1678. _strName.bUpdate( pszName );
  1679. _strMonitor.bUpdate( pszMonitor );
  1680. _strDescription.bUpdate( pszDescription );
  1681. _strPrinters.bUpdate( pszPrinters );
  1682. }
  1683. TPortsLV::TPortData::
  1684. ~TPortData(
  1685. VOID
  1686. )
  1687. {
  1688. DBGMSG( DBG_TRACE, ( "PortsLV::TPortData dtor\n" ) );
  1689. //
  1690. // If we are linked then remove ourself.
  1691. //
  1692. if( PortData_bLinked() )
  1693. {
  1694. PortData_vDelinkSelf();
  1695. }
  1696. }
  1697. BOOL
  1698. TPortsLV::TPortData::
  1699. bValid(
  1700. VOID
  1701. )
  1702. {
  1703. return VALID_OBJ( _strName ) &&
  1704. VALID_OBJ( _strMonitor ) &&
  1705. VALID_OBJ( _strDescription ) &&
  1706. VALID_OBJ( _strPrinters );
  1707. }