2183 lines
45 KiB
C++
2183 lines
45 KiB
C++
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
portslv.hxx
|
|
|
|
Abstract:
|
|
|
|
Ports List View header
|
|
|
|
Author:
|
|
|
|
Albert Ting (AlbertT) 17-Aug-1995
|
|
Steve Kiraly (SteveKi) 29-Mar-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "portslv.hxx"
|
|
|
|
#if DBG
|
|
//#define DBG_PORTSINFO DBG_INFO
|
|
#define DBG_PORTSINFO DBG_NONE
|
|
#endif
|
|
|
|
MSG_ERRMAP gaMsgErrMapPorts[] = {
|
|
ERROR_NOT_SUPPORTED, IDS_ERR_PORT_NOT_IMPLEMENTED,
|
|
ERROR_ALREADY_EXISTS, IDS_ERR_PORT_ALREADY_EXISTS,
|
|
0, 0
|
|
};
|
|
|
|
/********************************************************************
|
|
|
|
Ports List view class.
|
|
|
|
********************************************************************/
|
|
|
|
TPortsLV::
|
|
TPortsLV(
|
|
VOID
|
|
) : _bSelectionState( TRUE ),
|
|
_bSingleSelection( TRUE ),
|
|
_bTwoColumnMode( FALSE ),
|
|
_iSelectedItem( -1 ),
|
|
_ColumnSortState( kPortHeaderMax ),
|
|
_uCurrentColumn( 0 ),
|
|
_bAllowSelectionChange( FALSE ),
|
|
_bHideFaxPorts( FALSE )
|
|
{
|
|
vCreatePortDataList();
|
|
}
|
|
|
|
TPortsLV::
|
|
~TPortsLV(
|
|
VOID
|
|
)
|
|
{
|
|
vDestroyPortDataList();
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bReloadPorts(
|
|
IN LPCTSTR pszServerName,
|
|
IN BOOL bSelectNewPort
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read in the remote ports and put them in the listview. If level
|
|
2 fails, we will try 1.
|
|
|
|
Arguments:
|
|
|
|
pszServerName - Pointer to server name.
|
|
bSelectNewPort - Indicates if a new port is to be located and selected.
|
|
TRUE select new port, FALSE do not located new port.
|
|
|
|
Return Value:
|
|
|
|
TRUE if ports list loaded, FALSE if error occurred.
|
|
|
|
--*/
|
|
|
|
{
|
|
TStatusB bStatus( DBG_WARN, ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_LEVEL );
|
|
|
|
DWORD cbPorts = 0;
|
|
PPORT_INFO_2 pPorts = NULL;
|
|
DWORD cPorts = 0;
|
|
DWORD dwLevel = 2;
|
|
|
|
//
|
|
// Preserve the current check state.
|
|
//
|
|
TCHAR szPortList[kPortListMax];
|
|
vGetPortList( szPortList, COUNTOF( szPortList ) );
|
|
|
|
//
|
|
// Enumerate the port starting at level 2.
|
|
//
|
|
bStatus DBGCHK = VDataRefresh::bEnumPortsMaxLevel( pszServerName,
|
|
&dwLevel,
|
|
(PVOID *)&pPorts,
|
|
&cbPorts,
|
|
&cPorts );
|
|
|
|
//
|
|
// If the ports list cannot be enumerated fail with an error.
|
|
//
|
|
if( !bStatus ){
|
|
DBGMSG( DBG_WARN, ( "PortsLV.bReloadPorts: can't alloc %d %d\n", cbPorts, GetLastError( )));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If option to select newly added port was selected.
|
|
//
|
|
TString strNewPort;
|
|
if( bSelectNewPort ){
|
|
|
|
//
|
|
// Located the newly added port.
|
|
//
|
|
bSelectNewPort = bLocateAddedPort( strNewPort, pPorts, cPorts, dwLevel );
|
|
if( bSelectNewPort ){
|
|
DBGMSG( DBG_TRACE, ("New port found " TSTR "\n", (LPCTSTR)strNewPort ) );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the printers
|
|
//
|
|
PRINTER_INFO_2 *pPrinterInfo2 = NULL;
|
|
DWORD cPrinterInfo2 = 0;
|
|
DWORD cbPrinterInfo2 = 0;
|
|
DWORD dwFlags = PRINTER_ENUM_NAME;
|
|
|
|
bStatus DBGCHK = VDataRefresh::bEnumPrinters(
|
|
dwFlags,
|
|
(LPTSTR)pszServerName,
|
|
2,
|
|
(PVOID *)&pPrinterInfo2,
|
|
&cbPrinterInfo2,
|
|
&cPrinterInfo2 );
|
|
|
|
//
|
|
// Delete current ports if they exist.
|
|
//
|
|
bStatus DBGCHK = ListView_DeleteAllItems( _hwndLV );
|
|
|
|
//
|
|
// Clear the item count.
|
|
//
|
|
_cLVPorts = 0;
|
|
|
|
//
|
|
// Delete all the port data items.
|
|
//
|
|
vDestroyPortDataList();
|
|
|
|
TString strDescription;
|
|
|
|
//
|
|
// Add LPT?: ports
|
|
//
|
|
strDescription.bLoadString( ghInst, IDS_TEXT_PRINTERPORT );
|
|
vInsertPortsByMask(
|
|
cPorts,
|
|
pPorts,
|
|
cPrinterInfo2,
|
|
pPrinterInfo2,
|
|
dwLevel,
|
|
TEXT("lpt?:"),
|
|
strDescription
|
|
);
|
|
|
|
//
|
|
// Add COM?: ports
|
|
//
|
|
strDescription.bLoadString( ghInst, IDS_TEXT_SERIALPORT );
|
|
vInsertPortsByMask(
|
|
cPorts,
|
|
pPorts,
|
|
cPrinterInfo2,
|
|
pPrinterInfo2,
|
|
dwLevel,
|
|
TEXT("com?:"),
|
|
strDescription
|
|
);
|
|
|
|
//
|
|
// Add FILE: ports
|
|
//
|
|
strDescription.bLoadString( ghInst, IDS_TEXT_PRINTTOFILE );
|
|
vInsertPortsByMask(
|
|
cPorts,
|
|
pPorts,
|
|
cPrinterInfo2,
|
|
pPrinterInfo2,
|
|
dwLevel,
|
|
TEXT("file:"),
|
|
strDescription
|
|
);
|
|
|
|
//
|
|
// Add all the rest
|
|
//
|
|
vInsertPortsByMask(
|
|
cPorts,
|
|
pPorts,
|
|
cPrinterInfo2,
|
|
pPrinterInfo2,
|
|
dwLevel,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Restore the previous check state.
|
|
//
|
|
vCheckPorts( szPortList );
|
|
|
|
//
|
|
// Select and check the newly added port.
|
|
//
|
|
if( bSelectNewPort ){
|
|
|
|
//
|
|
// Check off other selected ports
|
|
//
|
|
INT iItem = -1;
|
|
|
|
do
|
|
{
|
|
iItem = ListView_GetNextItem( _hwndLV, iItem, LVNI_SELECTED );
|
|
|
|
if( iItem != -1 )
|
|
{
|
|
ListView_SetItemState( _hwndLV,
|
|
iItem,
|
|
0,
|
|
LVIS_SELECTED | LVIS_FOCUSED );
|
|
}
|
|
} while( iItem != -1 );
|
|
|
|
//
|
|
// New port is added select and scroll it into view.
|
|
//
|
|
vItemClicked( iSelectPort( strNewPort ) );
|
|
}
|
|
|
|
//
|
|
// This arrays of numbers represents the percentages of
|
|
// each column width from the total LV width. The sum
|
|
// of all numbers in the array should be equal to 100
|
|
// (100% = the total LV width)
|
|
//
|
|
static UINT arrColW2[] = { 50, 50 };
|
|
static UINT arrColW3[] = { 18, 35, 47 };
|
|
|
|
//
|
|
// Adjust columns ...
|
|
//
|
|
if( !_bTwoColumnMode )
|
|
{
|
|
vAdjustHeaderColumns( _hwndLV, COUNTOF(arrColW3), arrColW3 );
|
|
}
|
|
else
|
|
{
|
|
vAdjustHeaderColumns( _hwndLV, COUNTOF(arrColW2), arrColW2 );
|
|
}
|
|
|
|
//
|
|
// Release the enum ports and enum printer memory.
|
|
//
|
|
FreeMem( pPorts );
|
|
FreeMem( pPrinterInfo2 );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bLocateAddedPort(
|
|
IN LPCTSTR pszServerName,
|
|
IN TString &strNewPort
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Located the first port which is not in the port list view.
|
|
|
|
Arguments:
|
|
|
|
strPort - New port which has been added.
|
|
|
|
Return Value:
|
|
|
|
TRUE success, FALSE error occurred.
|
|
|
|
--*/
|
|
{
|
|
TStatusB bStatus;
|
|
DWORD cbPorts = 0;
|
|
PPORT_INFO_2 pPorts = NULL;
|
|
DWORD cPorts = 0;
|
|
DWORD dwLevel = 2;
|
|
|
|
//
|
|
// Enumerate the port starting at level 2.
|
|
//
|
|
bStatus DBGCHK = VDataRefresh::bEnumPortsMaxLevel( pszServerName,
|
|
&dwLevel,
|
|
(PVOID *)&pPorts,
|
|
&cbPorts,
|
|
&cPorts );
|
|
|
|
//
|
|
// If the ports list cannot be enumerated fail with an error.
|
|
//
|
|
if( bStatus )
|
|
{
|
|
//
|
|
// Located the newly added port.
|
|
//
|
|
bStatus DBGCHK = bLocateAddedPort( strNewPort, pPorts, cPorts, dwLevel );
|
|
|
|
if( bStatus )
|
|
{
|
|
DBGMSG( DBG_TRACE, ("New port found " TSTR "\n", (LPCTSTR)strNewPort ) );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Release the port memory.
|
|
//
|
|
FreeMem( pPorts );
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bLocateAddedPort(
|
|
IN OUT TString &strPort,
|
|
IN PPORT_INFO_2 pPorts,
|
|
IN DWORD cPorts,
|
|
IN DWORD dwLevel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Located the first port which is not in the port list view.
|
|
|
|
Arguments:
|
|
|
|
strPort - New port which has been added.
|
|
pPorts - Points to a ports enum structure array.
|
|
cPorts - Number of elements in the ports enum array.
|
|
dwLevel - Level of the ports enum structure array.
|
|
|
|
Return Value:
|
|
|
|
TRUE success, FALSE error occurred.
|
|
|
|
--*/
|
|
{
|
|
TStatusB bStatus;
|
|
LPTSTR pszPort;
|
|
|
|
bStatus DBGNOCHK = FALSE;
|
|
|
|
//
|
|
// Go through all the ports.
|
|
//
|
|
for( UINT i=0; i<cPorts; ++i ){
|
|
|
|
if( dwLevel == 2 ){
|
|
|
|
//
|
|
// If we are to hide the fax ports then
|
|
// ignore newly added fax ports.
|
|
//
|
|
if( _bHideFaxPorts && bIsFaxPort( pPorts[i].pPortName, pPorts[i].pMonitorName ) )
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "PortsLV.bLocateAddedPort: fax device being skipped.\n" ) );
|
|
continue;
|
|
}
|
|
|
|
pszPort = pPorts[i].pPortName;
|
|
|
|
} else {
|
|
pszPort = ((PPORT_INFO_1)pPorts)[i].pName;
|
|
}
|
|
|
|
//
|
|
// Look for a portname which is not in the list view.
|
|
//
|
|
if( iFindPort( pszPort ) < 0 ){
|
|
|
|
//
|
|
// Update the passed in string object.
|
|
//
|
|
bStatus DBGCHK = strPort.bUpdate( pszPort );
|
|
break;
|
|
}
|
|
}
|
|
return bStatus;
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vSelectPort(
|
|
IN LPCTSTR pszPort
|
|
)
|
|
{
|
|
SPLASSERT( pszPort );
|
|
iSelectPort( pszPort );
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vEnable(
|
|
IN BOOL bRetainSelection
|
|
)
|
|
{
|
|
if( bRetainSelection )
|
|
{
|
|
if( _iSelectedItem != -1 )
|
|
{
|
|
ListView_SetItemState( _hwndLV,
|
|
_iSelectedItem,
|
|
LVIS_SELECTED | LVIS_FOCUSED,
|
|
LVIS_SELECTED | LVIS_FOCUSED );
|
|
|
|
ListView_EnsureVisible( _hwndLV,
|
|
_iSelectedItem,
|
|
FALSE );
|
|
}
|
|
}
|
|
EnableWindow( _hwndLV, TRUE );
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vDisable(
|
|
IN BOOL bRetainSelection
|
|
)
|
|
{
|
|
if( bRetainSelection )
|
|
{
|
|
_iSelectedItem = ListView_GetNextItem( _hwndLV, -1, LVNI_SELECTED );
|
|
|
|
if( _iSelectedItem != -1 )
|
|
{
|
|
ListView_SetItemState( _hwndLV,
|
|
_iSelectedItem,
|
|
0,
|
|
LVIS_SELECTED | LVIS_FOCUSED );
|
|
}
|
|
}
|
|
EnableWindow( _hwndLV, FALSE );
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vCheckPorts(
|
|
IN OUT LPTSTR pszPortString CHANGE
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the ports in the listview based on the printers port string.
|
|
|
|
Arguments:
|
|
|
|
pszPortName - List of ports, comma delimited. When this is returns,
|
|
pszPortName is the same on entry, but it's modified inside this
|
|
function.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// We will walk though the port string, replacing commas with
|
|
// NULLs, but we'll change them back.
|
|
//
|
|
LPTSTR psz = pszPortString;
|
|
SPLASSERT( psz );
|
|
|
|
LPTSTR pszPort;
|
|
INT iItem;
|
|
INT iItemFirst = kMaxInt;
|
|
|
|
while( psz && *psz ){
|
|
|
|
pszPort = psz;
|
|
psz = _tcschr( psz, TEXT( ',' ));
|
|
|
|
if( psz ){
|
|
*psz = 0;
|
|
}
|
|
|
|
iItem = iCheckPort( pszPort );
|
|
if( iItem == -1 ){
|
|
DBGMSG( DBG_WARN,
|
|
( "PortsLV.vCheckPort: Port "TSTR" not checked.\n", pszPort ));
|
|
}
|
|
|
|
if( iItem < iItemFirst ){
|
|
iItemFirst = iItem;
|
|
}
|
|
|
|
if( psz ){
|
|
*psz = TEXT( ',' );
|
|
++psz;
|
|
}
|
|
}
|
|
|
|
if( iItemFirst == kMaxInt ){
|
|
|
|
DBGMSG( DBG_PORTSINFO, ( "PortsLV.vCheckPorts: No ports selected.\n" ));
|
|
iItemFirst = 0;
|
|
}
|
|
|
|
//
|
|
// Select the first item and make sure it is visible.
|
|
//
|
|
ListView_SetItemState( _hwndLV,
|
|
iItemFirst,
|
|
LVIS_SELECTED | LVIS_FOCUSED,
|
|
LVIS_SELECTED | LVIS_FOCUSED );
|
|
|
|
ListView_EnsureVisible( _hwndLV,
|
|
iItemFirst,
|
|
FALSE );
|
|
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vSelectItem(
|
|
INT iItem
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Selects an item in the ListView.
|
|
|
|
Arguments:
|
|
|
|
iItem - Index of item to select.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
ListView_SetItemState( _hwndLV,
|
|
iItem,
|
|
LVIS_SELECTED,
|
|
LVIS_SELECTED );
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bSetUI(
|
|
IN HWND hwndLV,
|
|
IN BOOL bTwoColumnMode,
|
|
IN BOOL bSelectionState,
|
|
IN BOOL bAllowSelectionChange,
|
|
IN HWND hwnd,
|
|
IN WPARAM wmDoubleClickMsg,
|
|
IN WPARAM wmSingleClickMsg,
|
|
IN WPARAM wmDeleteKeyMsg
|
|
)
|
|
{
|
|
_hwndLV = hwndLV;
|
|
_bTwoColumnMode = bTwoColumnMode;
|
|
_bSelectionState = bSelectionState;
|
|
_bAllowSelectionChange = bAllowSelectionChange;
|
|
_wmDoubleClickMsg = wmDoubleClickMsg;
|
|
_wmSingleClickMsg = wmSingleClickMsg;
|
|
_wmDeleteKeyMsg = wmDeleteKeyMsg;
|
|
_hwnd = hwnd;
|
|
|
|
SPLASSERT( _hwndLV );
|
|
|
|
if( _bSelectionState ){
|
|
|
|
//
|
|
// Add check boxes.
|
|
//
|
|
HIMAGELIST himlState = ImageList_Create( 16, 16, TRUE, 2, 0 );
|
|
|
|
//
|
|
// !! LATER !!
|
|
// Should be created once then shared.
|
|
//
|
|
if( !himlState ){
|
|
DBGMSG( DBG_ERROR, ( "PortsLV.bSetUI: ImageList_Create failed %d\n",
|
|
GetLastError( )));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Load the bitmap for the check states.
|
|
//
|
|
HBITMAP hbm = LoadBitmap( ghInst, MAKEINTRESOURCE( IDB_CHECKSTATES ));
|
|
|
|
if( !hbm ){
|
|
DBGMSG( DBG_ERROR, ( "PortsLV.bSetUI: LoadBitmap failed %d\n",
|
|
GetLastError( )));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Add the bitmaps to the image list.
|
|
//
|
|
ImageList_AddMasked( himlState, hbm, RGB( 255, 0, 0 ));
|
|
|
|
SendMessage( _hwndLV, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himlState );
|
|
|
|
DeleteObject( hbm );
|
|
|
|
}
|
|
|
|
INT iNumColumns = _bTwoColumnMode ? 2 : kPortHeaderMax;
|
|
|
|
//
|
|
// Initialize the LV_COLUMN structure.
|
|
//
|
|
LV_COLUMN lvc;
|
|
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
|
|
lvc.fmt = LVCFMT_LEFT;
|
|
lvc.cx = kPortHeaderWidthDefault;
|
|
|
|
RECT rc;
|
|
if( !GetClientRect( _hwndLV, &rc )){
|
|
|
|
DBGMSG( DBG_WARN, ( "PortsLV.bSetUI: GetClientRect failed %d\n", GetLastError( )));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Calculate the column width, less the scroll bar width.
|
|
//
|
|
lvc.cx = ( ( rc.right - rc.left ) - GetSystemMetrics( SM_CYVSCROLL ) ) / iNumColumns;
|
|
|
|
TStatusB bStatus;
|
|
TString strHeader;
|
|
|
|
for( INT iCol = 0; iCol < iNumColumns; ++iCol ){
|
|
|
|
bStatus DBGCHK = strHeader.bLoadString( ghInst, IDS_PHEAD_BEGIN + iCol );
|
|
lvc.pszText = (LPTSTR)(LPCTSTR)strHeader;
|
|
lvc.iSubItem = iCol;
|
|
|
|
if( ListView_InsertColumn( _hwndLV, iCol, &lvc ) == -1 ){
|
|
|
|
DBGMSG( DBG_WARN, ( "PortsLV.bSetUI: LV_Insert failed %d\n", GetLastError( )));
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Enable full row selection.
|
|
//
|
|
DWORD dwExStyle = ListView_GetExtendedListViewStyle( _hwndLV );
|
|
ListView_SetExtendedListViewStyle( _hwndLV, dwExStyle | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_LABELTIP );
|
|
|
|
//
|
|
// !!LATER!!
|
|
// We should read an override flag from the registry.
|
|
//
|
|
_bHideFaxPorts = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vAddPortToListView(
|
|
IN LPCTSTR pszName,
|
|
IN LPCTSTR pszMonitor,
|
|
IN LPCTSTR pszDescription,
|
|
IN LPCTSTR pszPrinters
|
|
)
|
|
{
|
|
if( !pszName || !pszName[0] ){
|
|
DBGMSG( DBG_WARN,
|
|
( "PortsLV.vAddPortToListView: pszName "TSTR" invalid\n",
|
|
DBGSTR( pszName )));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// If we are to hide the fax ports and this is a fax
|
|
// port then just return with out adding the port to
|
|
// the list view.
|
|
//
|
|
if( _bHideFaxPorts && bIsFaxPort( pszName, pszMonitor ) )
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "PortsLV.vAddPortToListView: fax device being removed.\n" ) );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Add this port to the port data list.
|
|
//
|
|
TPortData *pPortData = AddPortDataList( pszName, pszMonitor, pszDescription, pszPrinters );
|
|
|
|
LV_ITEM lvi;
|
|
|
|
if( _bSelectionState ){
|
|
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
|
|
} else {
|
|
lvi.mask = LVIF_TEXT | LVIF_PARAM;
|
|
}
|
|
|
|
lvi.state = kStateUnchecked;
|
|
lvi.pszText = (LPTSTR)pszName;
|
|
lvi.iItem = _cLVPorts;
|
|
lvi.iSubItem = 0;
|
|
lvi.lParam = (LPARAM)pPortData;
|
|
|
|
ListView_InsertItem( _hwndLV, &lvi );
|
|
ListView_SetItemText( _hwndLV, _cLVPorts, 1, (LPTSTR)pszDescription );
|
|
|
|
if( !_bTwoColumnMode )
|
|
{
|
|
ListView_SetItemText( _hwndLV, _cLVPorts, 2, (LPTSTR)pszPrinters );
|
|
}
|
|
|
|
++_cLVPorts;
|
|
}
|
|
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vDeletePortFromListView(
|
|
IN LPCTSTR pszName
|
|
)
|
|
{
|
|
|
|
//
|
|
// Locate the port in the list view.
|
|
//
|
|
INT iItem = iFindPort ( pszName );
|
|
|
|
if( iItem != -1 ){
|
|
|
|
//
|
|
// Delete this port from the port data list.
|
|
//
|
|
DeletePortDataList( pszName );
|
|
|
|
ListView_DeleteItem( _hwndLV, iItem );
|
|
|
|
//
|
|
// Select next item. If the item we just deleted is the last item,
|
|
// we need to select the previous one.
|
|
//
|
|
// If we deleted the last item, leave it as is.
|
|
//
|
|
if( ListView_GetItemCount( _hwndLV ) == iItem &&
|
|
iItem > 0 ) {
|
|
--iItem;
|
|
}
|
|
|
|
ListView_SetItemState( _hwndLV,
|
|
iItem,
|
|
LVIS_SELECTED | LVIS_FOCUSED,
|
|
LVIS_SELECTED | LVIS_FOCUSED );
|
|
}
|
|
}
|
|
|
|
INT
|
|
TPortsLV::
|
|
iFindPort(
|
|
IN LPCTSTR pszPort
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Located the specified port name in the list view.
|
|
|
|
Arguments:
|
|
|
|
pszPort - Port name to locate.
|
|
|
|
Return Value:
|
|
|
|
iItem id if found, -1 if item was not found.
|
|
|
|
--*/
|
|
{
|
|
SPLASSERT( pszPort );
|
|
|
|
LV_FINDINFO lvfi;
|
|
|
|
lvfi.flags = LVFI_STRING;
|
|
lvfi.psz = pszPort;
|
|
|
|
INT iItem = ListView_FindItem( _hwndLV, -1, &lvfi );
|
|
|
|
if( iItem == -1 ){
|
|
DBGMSG( DBG_WARN, ( "PortsLV.iFindPort: port "TSTR" not found\n", pszPort ));
|
|
}
|
|
|
|
return iItem;
|
|
}
|
|
|
|
|
|
INT
|
|
TPortsLV::
|
|
iCheckPort(
|
|
IN LPCTSTR pszPort
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Places the check mark next to a port in the list view.
|
|
|
|
Arguments:
|
|
|
|
pszPort - Port to check.
|
|
|
|
Return Value:
|
|
|
|
iItem checked, -1 == error.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Locate the port in the list view.
|
|
//
|
|
INT iItem = iFindPort ( pszPort );
|
|
|
|
if( iItem != -1 ){
|
|
|
|
//
|
|
// Set the item selection state.
|
|
//
|
|
ListView_SetItemState( _hwndLV,
|
|
iItem,
|
|
kStateChecked,
|
|
kStateMask );
|
|
|
|
//
|
|
// Try and make as many ports visible as possible.
|
|
//
|
|
ListView_EnsureVisible( _hwndLV,
|
|
iItem,
|
|
FALSE );
|
|
}
|
|
|
|
return iItem;
|
|
}
|
|
|
|
INT
|
|
TPortsLV::
|
|
iSelectPort(
|
|
IN LPCTSTR pszPort
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Select the port in the list view.
|
|
|
|
Arguments:
|
|
|
|
pszPort - Port to check.
|
|
|
|
Return Value:
|
|
|
|
iItem checked, -1 == error.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Locate the port in the list view.
|
|
//
|
|
INT iItem = iFindPort ( pszPort );
|
|
|
|
if( iItem != -1 ){
|
|
|
|
//
|
|
// Select the port specified by pszPort.
|
|
//
|
|
ListView_SetItemState( _hwndLV,
|
|
iItem,
|
|
LVIS_SELECTED | LVIS_FOCUSED,
|
|
LVIS_SELECTED | LVIS_FOCUSED );
|
|
//
|
|
// Try and make as many ports visible as possible.
|
|
//
|
|
ListView_EnsureVisible( _hwndLV,
|
|
iItem,
|
|
FALSE );
|
|
}
|
|
|
|
return iItem;
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vGetPortList(
|
|
OUT LPTSTR pszPortList,
|
|
IN COUNT cchPortList
|
|
)
|
|
{
|
|
INT cPorts = 0;
|
|
DWORD i;
|
|
|
|
LV_ITEM lvi;
|
|
|
|
LPTSTR pszPort = pszPortList;
|
|
DWORD cchSpaceLeft = cchPortList - 1;
|
|
DWORD cchLen;
|
|
lvi.iSubItem = 0;
|
|
|
|
DWORD cItems = ListView_GetItemCount( _hwndLV );
|
|
|
|
for( pszPortList[0] = 0, i=0; i<cItems; ++i ){
|
|
|
|
if( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked ){
|
|
|
|
lvi.pszText = pszPort;
|
|
lvi.cchTextMax = cchSpaceLeft;
|
|
|
|
cchLen = (DWORD)SendMessage( _hwndLV,
|
|
LVM_GETITEMTEXT,
|
|
(WPARAM)i,
|
|
(LPARAM)&lvi );
|
|
|
|
if( cchLen + 1 > cchSpaceLeft ){
|
|
|
|
DBGMSG( DBG_WARN, ( "PortsLV.iGetPorts: Out of string space!\n" ));
|
|
return;
|
|
}
|
|
|
|
pszPort += cchLen;
|
|
cchSpaceLeft -= cchLen+1;
|
|
|
|
*pszPort = TEXT( ',' );
|
|
++pszPort;
|
|
++cPorts;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we had any ports, back up to remove the last comma.
|
|
//
|
|
if( cPorts ){
|
|
--pszPort;
|
|
}
|
|
|
|
//
|
|
// Null terminate.
|
|
//
|
|
*pszPort = 0;
|
|
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bReadUI(
|
|
OUT TString &strPortString,
|
|
IN BOOL bSelectedPort
|
|
)
|
|
{
|
|
TCHAR szPortList[kPortListMax];
|
|
szPortList[0] = 0;
|
|
|
|
//
|
|
// If we are in single select mode just return
|
|
// the selected port.
|
|
//
|
|
if( bSelectedPort )
|
|
{
|
|
(VOID)bGetSelectedPort( szPortList, COUNTOF( szPortList ) );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Get the list of check ports from the list view.
|
|
//
|
|
vGetPortList( szPortList, COUNTOF( szPortList ) );
|
|
}
|
|
|
|
//
|
|
// Update the port list.
|
|
//
|
|
return strPortString.bUpdate( szPortList );
|
|
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vItemClicked(
|
|
IN INT iItem
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
User clicked in listview. Check if item state should
|
|
be changed.
|
|
|
|
The item will also be selected.
|
|
|
|
Arguments:
|
|
|
|
iItem - Item that has been clicked.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
if( iItem == -1 ){
|
|
DBGMSG( DBG_WARN, ( "PortsLV.vItemClicked: -1 passed in\n" ));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// If in single selection mode clear all items checked and only
|
|
// check the specified item.
|
|
//
|
|
if( _bSingleSelection ){
|
|
|
|
DWORD cItems = ListView_GetItemCount( _hwndLV );
|
|
|
|
for( UINT i=0; i<cItems; ++i ){
|
|
|
|
if( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked ){
|
|
|
|
if( iItem == (INT)i ){
|
|
continue;
|
|
} else {
|
|
|
|
ListView_SetItemState( _hwndLV,
|
|
i,
|
|
kStateUnchecked,
|
|
kStateMask );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Retrieve the old state, toggle it, then set it.
|
|
//
|
|
DWORD dwState = ListView_GetItemState( _hwndLV,
|
|
iItem,
|
|
kStateMask );
|
|
|
|
//
|
|
// When we are in single select mode we want to always check
|
|
// the currently selected item.
|
|
//
|
|
if( !_bSingleSelection )
|
|
{
|
|
dwState = ( dwState == kStateChecked ) ?
|
|
kStateUnchecked | LVIS_SELECTED | LVIS_FOCUSED :
|
|
kStateChecked | LVIS_SELECTED | LVIS_FOCUSED;
|
|
}
|
|
else
|
|
{
|
|
dwState = kStateChecked | LVIS_SELECTED | LVIS_FOCUSED;
|
|
}
|
|
|
|
//
|
|
// Set the new item state.
|
|
//
|
|
ListView_SetItemState( _hwndLV,
|
|
iItem,
|
|
dwState,
|
|
kStateMask | LVIS_SELECTED | LVIS_FOCUSED );
|
|
|
|
}
|
|
|
|
COUNT
|
|
TPortsLV::
|
|
cSelectedPorts(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the number of items which have a check mark
|
|
next to them.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Return the number of checked items.
|
|
|
|
--*/
|
|
{
|
|
DWORD cItems = ListView_GetItemCount( _hwndLV );
|
|
COUNT cItemsSelected = 0;
|
|
DWORD i;
|
|
|
|
for( i = 0; i < cItems; ++i )
|
|
{
|
|
if( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked )
|
|
{
|
|
++cItemsSelected;
|
|
}
|
|
}
|
|
|
|
return cItemsSelected;
|
|
}
|
|
|
|
COUNT
|
|
TPortsLV::
|
|
cSelectedItems(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the number of items which are currently selected.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Return the number of selected items.
|
|
|
|
--*/
|
|
{
|
|
DWORD cItems = ListView_GetItemCount( _hwndLV );
|
|
COUNT cItemsSelected = 0;
|
|
DWORD i;
|
|
|
|
for( i = 0; i < cItems; ++i )
|
|
{
|
|
if( ListView_GetItemState( _hwndLV, i, LVIS_SELECTED ) & LVIS_SELECTED )
|
|
{
|
|
++cItemsSelected;
|
|
}
|
|
}
|
|
|
|
return cItemsSelected;
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vRemoveAllChecks(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Removes all the check marks for the list view.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
{
|
|
DWORD cItems = ListView_GetItemCount( _hwndLV );
|
|
COUNT cItemsSelected = 0;
|
|
DWORD i;
|
|
|
|
for( i=0; i<cItems; ++i ){
|
|
|
|
if( ListView_GetItemState( _hwndLV, i, kStateMask ) & kStateChecked ){
|
|
|
|
ListView_SetItemState( _hwndLV,
|
|
i,
|
|
kStateUnchecked,
|
|
kStateMask );
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vSetFocus(
|
|
VOID
|
|
)
|
|
{
|
|
SetFocus( _hwndLV );
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bGetSelectedPort(
|
|
OUT LPTSTR pszPort,
|
|
IN COUNT cchPort
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieve the currently selected port in the list view.
|
|
|
|
Arguments:
|
|
|
|
pszPort - TCHAR array to receive port
|
|
|
|
cchPort - COUNTOF port string.
|
|
|
|
Return Value:
|
|
|
|
TRUE - success, FALSE = fail.
|
|
|
|
--*/
|
|
|
|
{
|
|
INT iItem = ListView_GetNextItem( _hwndLV,
|
|
-1,
|
|
LVNI_SELECTED );
|
|
if( iItem == -1 ){
|
|
|
|
DBGMSG( DBG_WARN,
|
|
( "PrinterPort.bGetSelectedPort: Unable to retrieve next selected item %d\n",
|
|
GetLastError( )));
|
|
return FALSE;
|
|
}
|
|
|
|
ListView_GetItemText( _hwndLV,
|
|
iItem,
|
|
0,
|
|
pszPort,
|
|
cchPort );
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bGetSelectedPort(
|
|
OUT LPTSTR pszPort,
|
|
IN COUNT cchPort,
|
|
INT *pItem
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrieve the currently selected port in the list view.
|
|
|
|
Arguments:
|
|
|
|
pszPort - TCHAR array to receive port
|
|
|
|
cchPort - COUNTOF port string.
|
|
|
|
iItem - Index of the item with which to begin the search
|
|
|
|
Return Value:
|
|
|
|
TRUE - success, FALSE = fail.
|
|
iItem will be set to the new found index.
|
|
|
|
--*/
|
|
|
|
{
|
|
INT iItem = *pItem;
|
|
|
|
iItem = ListView_GetNextItem( _hwndLV,
|
|
iItem,
|
|
LVNI_SELECTED );
|
|
if( iItem == -1 ){
|
|
|
|
DBGMSG( DBG_WARN,
|
|
( "PrinterPort.bGetSelectedPort: Unable to retrieve next selected item %d\n",
|
|
GetLastError( )));
|
|
return FALSE;
|
|
}
|
|
|
|
ListView_GetItemText( _hwndLV,
|
|
iItem,
|
|
0,
|
|
pszPort,
|
|
cchPort );
|
|
|
|
*pItem = iItem;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bHandleNotifyMessage(
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
BOOL bStatus = TRUE;
|
|
LPNMHDR pnmh = (LPNMHDR)lParam;
|
|
|
|
switch( pnmh->code )
|
|
{
|
|
case NM_DBLCLK:
|
|
|
|
vHandleItemClicked( lParam );
|
|
|
|
if( _wmDoubleClickMsg )
|
|
{
|
|
PostMessage( _hwnd, WM_COMMAND, _wmDoubleClickMsg, 0 );
|
|
}
|
|
break;
|
|
|
|
case NM_CLICK:
|
|
|
|
vHandleItemClicked( lParam );
|
|
|
|
if( _wmSingleClickMsg )
|
|
{
|
|
PostMessage( _hwnd, WM_COMMAND, _wmSingleClickMsg, 0 );
|
|
}
|
|
break;
|
|
|
|
case LVN_KEYDOWN:
|
|
{
|
|
LV_KEYDOWN* plvnkd = (LV_KEYDOWN *)lParam;
|
|
|
|
if( _bSelectionState && _bAllowSelectionChange )
|
|
{
|
|
//
|
|
// !! LATER !!
|
|
//
|
|
// Is this the best way to check whether the ALT
|
|
// key is _not_ down?
|
|
//
|
|
if( plvnkd->wVKey == TEXT( ' ' ) &&
|
|
!( GetKeyState( VK_LMENU ) & 0x80000000 ) &&
|
|
!( GetKeyState( VK_RMENU ) & 0x80000000 ))
|
|
{
|
|
vItemClicked( ListView_GetNextItem( _hwndLV, -1, LVNI_SELECTED ));
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the delete key was used then post a message to
|
|
// appropriate window with the specified message.
|
|
//
|
|
if(plvnkd->wVKey == VK_DELETE )
|
|
{
|
|
if( _wmDeleteKeyMsg )
|
|
{
|
|
PostMessage( _hwnd, WM_COMMAND, _wmDeleteKeyMsg, 0 );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LVN_COLUMNCLICK:
|
|
{
|
|
NM_LISTVIEW *pNm = (NM_LISTVIEW *)lParam;
|
|
(VOID)bListViewSort( pNm->iSubItem );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
bStatus = FALSE;
|
|
break;
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vHandleItemClicked(
|
|
IN LPARAM lParam
|
|
)
|
|
{
|
|
if( _bSelectionState && _bAllowSelectionChange )
|
|
{
|
|
LV_HITTESTINFO lvhti;
|
|
DWORD dwPos = GetMessagePos();
|
|
POINTS &pt = MAKEPOINTS(dwPos);
|
|
|
|
lvhti.pt.x = pt.x;
|
|
lvhti.pt.y = pt.y;
|
|
|
|
MapWindowPoints( HWND_DESKTOP, _hwndLV, &lvhti.pt, 1 );
|
|
|
|
INT iItem = ListView_HitTest( _hwndLV, &lvhti );
|
|
|
|
if( iItem != -1 )
|
|
{
|
|
vItemClicked( iItem );
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vInsertPortsByMask(
|
|
IN UINT cPorts,
|
|
IN PORT_INFO_2 pPorts[],
|
|
IN UINT cPrinters,
|
|
IN PRINTER_INFO_2 pPrinters[],
|
|
IN DWORD dwLevel,
|
|
IN LPCTSTR pszTemplate,
|
|
IN LPCTSTR pszDescription
|
|
)
|
|
{
|
|
TString strPrinters;
|
|
|
|
//
|
|
// Go through the ports and add them.
|
|
//
|
|
for( UINT i=0; i<cPorts; ++i )
|
|
{
|
|
if( dwLevel == 2 )
|
|
{
|
|
//
|
|
// Check if this port has been added
|
|
//
|
|
if( NULL == pPorts[i].pPortName )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check if the port name matches the template
|
|
//
|
|
if( pszTemplate && !bMatchTemplate( pszTemplate, pPorts[i].pPortName ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Assign proper description
|
|
//
|
|
LPCTSTR pszDescr = pszDescription;
|
|
if( !pszDescr )
|
|
{
|
|
pszDescr = pPorts[i].pDescription;
|
|
}
|
|
|
|
//
|
|
// If we have printers on this machine.
|
|
//
|
|
if( pPrinters && cPrinters )
|
|
{
|
|
vPrintersUsingPort( strPrinters, pPrinters, cPrinters, pPorts[i].pPortName );
|
|
}
|
|
|
|
vAddPortToListView( pPorts[i].pPortName, pPorts[i].pMonitorName, pszDescr, strPrinters );
|
|
|
|
//
|
|
// Mark the port as added
|
|
//
|
|
pPorts[i].pPortName = NULL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Check if this port has been added
|
|
//
|
|
if( NULL == ((PPORT_INFO_1)pPorts)[i].pName )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check if the port name matches the template
|
|
//
|
|
if( pszTemplate && !bMatchTemplate( pszTemplate, ((PPORT_INFO_1)pPorts)[i].pName ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// If we have printers on this machine.
|
|
//
|
|
if( pPrinters && cPrinters )
|
|
{
|
|
vPrintersUsingPort( strPrinters, pPrinters, cPrinters, ((PPORT_INFO_1)pPorts)[i].pName );
|
|
}
|
|
|
|
vAddPortToListView( ((PPORT_INFO_1)pPorts)[i].pName, gszNULL, gszNULL, strPrinters );
|
|
|
|
//
|
|
// Mark the port as added
|
|
//
|
|
((PPORT_INFO_1)pPorts)[i].pName = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bDeletePorts(
|
|
IN HWND hDlg,
|
|
IN LPCTSTR pszServer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete selected ports for given print server.
|
|
|
|
Arguments:
|
|
|
|
hDlg - dialog handle for port tab.
|
|
pszServer - print server name.
|
|
|
|
Return Value:
|
|
|
|
True if at least one port is deleted, false otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
TStatusB bStatus;
|
|
TCHAR szPortName[TPortsLV::kPortNameMax];
|
|
COUNT cItems;
|
|
INT iItem = -1;
|
|
INT i;
|
|
BOOL bFailed = FALSE;
|
|
BOOL bDeleted = FALSE;
|
|
|
|
//
|
|
// Check whether multi ports are selected
|
|
//
|
|
cItems = cSelectedItems();
|
|
|
|
if(cItems == 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the first selected port name to compose the warning message
|
|
//
|
|
bStatus DBGCHK = bGetSelectedPort( szPortName, COUNTOF( szPortName ) );
|
|
|
|
if( IDYES == iMessage( hDlg,
|
|
IDS_DELETE_PORT_TITLE,
|
|
cItems > 1 ? IDS_DELETE_PORTN : IDS_DELETE_PORT,
|
|
MB_YESNO | MB_ICONQUESTION,
|
|
kMsgNone,
|
|
NULL,
|
|
szPortName ))
|
|
{
|
|
//
|
|
// Try to delete all selected items
|
|
//
|
|
for( i = 0; i < (INT)cItems ; i++ )
|
|
{
|
|
//
|
|
// Get each selected port name
|
|
//
|
|
bStatus DBGCHK = bGetSelectedPort( szPortName, COUNTOF( szPortName ), &iItem );
|
|
|
|
SPLASSERT( bStatus );
|
|
SPLASSERT( iItem != -1 );
|
|
|
|
//
|
|
// Attempt to delete the selected port.
|
|
//
|
|
bStatus DBGCHK = DeletePort( (LPTSTR)pszServer, hDlg, szPortName );
|
|
|
|
if( bStatus )
|
|
{
|
|
//
|
|
// Succeeded, refresh the ports UI by deleting the port.
|
|
//
|
|
vDeletePortFromListView( szPortName );
|
|
|
|
//
|
|
// Decrease the iItem because deleting one item in the list
|
|
//
|
|
iItem--;
|
|
bDeleted = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if( GetLastError() != ERROR_CANCELLED )
|
|
{
|
|
bFailed = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Only show an error message if the did not cancel the
|
|
// the action.
|
|
//
|
|
if( bFailed )
|
|
{
|
|
iMessage( hDlg,
|
|
IDS_DELETE_PORT_TITLE,
|
|
cItems > 1 ? IDS_ERR_DELETE_PORTN : IDS_ERR_DELETE_PORT,
|
|
MB_OK | MB_ICONEXCLAMATION,
|
|
kMsgGetLastError,
|
|
gaMsgErrMapPorts);
|
|
}
|
|
|
|
bStatus DBGNOCHK = bDeleted;
|
|
}
|
|
else
|
|
{
|
|
bStatus DBGNOCHK = FALSE;
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bConfigurePort(
|
|
IN HWND hDlg,
|
|
IN LPCTSTR pszServer
|
|
)
|
|
{
|
|
static MSG_ERRMAP aMsgErrMapPorts[] = {
|
|
ERROR_INVALID_PARAMETER, IDS_ERR_PORT_DOES_NOT_EXIST,
|
|
0, 0
|
|
};
|
|
|
|
TStatusB bStatus;
|
|
TCHAR szPortName[TPortsLV::kPortNameMax];
|
|
|
|
bStatus DBGCHK = bGetSelectedPort( szPortName, COUNTOF( szPortName ) );
|
|
|
|
if( bStatus )
|
|
{
|
|
bStatus DBGCHK = ConfigurePort( (LPTSTR)pszServer,
|
|
hDlg,
|
|
szPortName );
|
|
|
|
if( !bStatus )
|
|
{
|
|
if( GetLastError() != ERROR_CANCELLED )
|
|
{
|
|
iMessage( hDlg,
|
|
IDS_CONFIGURE_PORT_TITLE,
|
|
IDS_ERR_CONFIG_PORT,
|
|
MB_OK | MB_ICONEXCLAMATION,
|
|
kMsgGetLastError,
|
|
aMsgErrMapPorts );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBGMSG( DBG_WARN, ( "PrinterPorts.vConfigure: failed %d\n", GetLastError( )));
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vPrintersUsingPort(
|
|
IN OUT TString &strPrinters,
|
|
IN PRINTER_INFO_2 *pPrinterInfo,
|
|
IN DWORD cPrinterInfo,
|
|
IN LPCTSTR pszPortName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Builds a comma separated string of all the printers
|
|
using the specified port.
|
|
|
|
Arguments:
|
|
|
|
strPrinters - TString refrence where to return resultant string.
|
|
pPrinterInfo - Pointer to a printer info level 2 structure array.
|
|
cPrinterInfo - Number of printers in the printer info 2 array.
|
|
pszPortName - Pointer to string or port name to match.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
Notes:
|
|
If no printer is using the specfied port the string refrence
|
|
will contain an empty string.
|
|
|
|
--*/
|
|
{
|
|
SPLASSERT( pPrinterInfo );
|
|
SPLASSERT( pszPortName );
|
|
|
|
LPTSTR psz;
|
|
LPTSTR pszPort;
|
|
LPTSTR pszPrinter;
|
|
UINT i;
|
|
|
|
//
|
|
// Clear the current printer buffer.
|
|
//
|
|
TStatusB bStatus;
|
|
bStatus DBGCHK = strPrinters.bUpdate( NULL );
|
|
|
|
//
|
|
// Traverse the printer info array.
|
|
//
|
|
for( i = 0; i < cPrinterInfo; i++ ){
|
|
|
|
for( psz = pPrinterInfo[i].pPortName; psz && *psz; ){
|
|
|
|
//
|
|
// Look for a comma if found terminate the port string.
|
|
//
|
|
pszPort = psz;
|
|
psz = _tcschr( psz, TEXT( ',' ) );
|
|
|
|
if( psz ){
|
|
*psz = 0;
|
|
}
|
|
|
|
//
|
|
// Check for a port match.
|
|
//
|
|
if( !_tcsicmp( pszPort, pszPortName ) ){
|
|
|
|
//
|
|
// Point to printer name.
|
|
//
|
|
pszPrinter = pPrinterInfo[i].pPrinterName;
|
|
|
|
//
|
|
// Strip the server name here.
|
|
//
|
|
if( pPrinterInfo[i].pPrinterName[0] == TEXT( '\\' ) &&
|
|
pPrinterInfo[i].pPrinterName[1] == TEXT( '\\' ) ){
|
|
|
|
//
|
|
// Locate the printer name.
|
|
//
|
|
pszPrinter = _tcschr( pPrinterInfo[i].pPrinterName+2, TEXT( '\\' ) );
|
|
pszPrinter = pszPrinter ? pszPrinter+1 : pPrinterInfo[i].pPrinterName;
|
|
|
|
}
|
|
|
|
//
|
|
// If this is the first time do not place a comma separator.
|
|
//
|
|
if( !strPrinters.bEmpty() ){
|
|
|
|
bStatus DBGCHK = strPrinters.bCat( TEXT( ", " ) );
|
|
|
|
if( !bStatus ){
|
|
DBGMSG( DBG_WARN, ( "Error cat string line: %d file : %s.\n", __LINE__, __FILE__ ) );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Tack on the printer name
|
|
//
|
|
bStatus DBGCHK = strPrinters.bCat( pszPrinter );
|
|
|
|
if( !bStatus ){
|
|
DBGMSG( DBG_WARN, ( "Error cat string line : %d file : %s.\n", __LINE__, __FILE__ ) );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Replace the previous comma.
|
|
//
|
|
if( psz ){
|
|
*psz = TEXT( ',' );
|
|
++psz;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vSetSingleSelection(
|
|
IN BOOL bSingleSelection
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the list view into single selection mode.
|
|
|
|
Arguments:
|
|
|
|
bSingleSelection - TRUE single selection, FALSE multi selection.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
{
|
|
_bSingleSelection = bSingleSelection;
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bGetSingleSelection(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the current list view selection mode.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TURE in single selection mode, FALSE in multi selection mode.
|
|
|
|
--*/
|
|
{
|
|
return _bSingleSelection;
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vCreatePortDataList(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the port data list.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "PortsLV::vCreatePortDataList\n" ) );
|
|
|
|
PortDataList_vReset();
|
|
}
|
|
|
|
VOID
|
|
TPortsLV::
|
|
vDestroyPortDataList(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destroy the port data list.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "PortsLV::vDestroyPortDataList\n" ) );
|
|
|
|
TIter Iter;
|
|
TPortData *pPortData;
|
|
|
|
for( PortDataList_vIterInit( Iter ), Iter.vNext(); Iter.bValid(); )
|
|
{
|
|
pPortData = PortDataList_pConvert( Iter );
|
|
Iter.vNext();
|
|
delete pPortData;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
bListViewSort(
|
|
IN UINT uColumn
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called to sort the items. The current
|
|
column indes is specified to indicated witch column to
|
|
sort.
|
|
|
|
Arguments:
|
|
|
|
Column index to sort.
|
|
|
|
Return Value:
|
|
|
|
TRUE list is sorted, FALSE error occurred.
|
|
|
|
--*/
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "PortsLV::bListViewSort Column %d\n", uColumn ) );
|
|
|
|
//
|
|
// Set the surrent column number.
|
|
//
|
|
_uCurrentColumn = uColumn;
|
|
|
|
//
|
|
// Tell the list view to sort.
|
|
//
|
|
TStatusB bStatus;
|
|
bStatus DBGCHK = ListView_SortItems( _hwndLV, iCompareProc, (LPARAM)this );
|
|
|
|
//
|
|
// Toggle the specified column sort state.
|
|
//
|
|
_ColumnSortState.bToggle( uColumn );
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
INT
|
|
CALLBACK
|
|
TPortsLV::
|
|
iCompareProc(
|
|
IN LPARAM lParam1,
|
|
IN LPARAM lParam2,
|
|
IN LPARAM RefData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
List view defined compare routine.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Nothing.
|
|
|
|
--*/
|
|
{
|
|
TPortData *pPortData1 = reinterpret_cast<TPortData *>( lParam1 );
|
|
TPortData *pPortData2 = reinterpret_cast<TPortData *>( lParam2 );
|
|
TPortsLV *pPortsLV = reinterpret_cast<TPortsLV *>( RefData );
|
|
INT iResult = 0;
|
|
LPCTSTR strName1 = NULL;
|
|
LPCTSTR strName2 = NULL;
|
|
|
|
if( pPortsLV && pPortData1 && pPortData2 )
|
|
{
|
|
BOOL bStatus = TRUE;
|
|
|
|
switch( pPortsLV->_uCurrentColumn )
|
|
{
|
|
|
|
case 0:
|
|
strName1 = pPortData1->_strName;
|
|
strName2 = pPortData2->_strName;
|
|
break;
|
|
|
|
case 1:
|
|
strName1 = pPortData1->_strDescription;
|
|
strName2 = pPortData2->_strDescription;
|
|
break;
|
|
|
|
case 2:
|
|
strName1 = pPortData1->_strPrinters;
|
|
strName2 = pPortData2->_strPrinters;
|
|
break;
|
|
|
|
default:
|
|
bStatus = FALSE;
|
|
break;
|
|
|
|
}
|
|
|
|
if( bStatus )
|
|
{
|
|
if( pPortsLV->_ColumnSortState.bRead( pPortsLV->_uCurrentColumn ) )
|
|
iResult = _tcsicmp( strName2, strName1 );
|
|
else
|
|
iResult = _tcsicmp( strName1, strName2 );
|
|
}
|
|
}
|
|
|
|
return iResult;
|
|
}
|
|
|
|
TPortsLV::TPortData *
|
|
TPortsLV::
|
|
AddPortDataList(
|
|
IN LPCTSTR pszName,
|
|
IN LPCTSTR pszMonitor,
|
|
IN LPCTSTR pszDescription,
|
|
IN LPCTSTR pszPrinters
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add port to port data list.
|
|
|
|
Arguments:
|
|
|
|
pszName - pointer to port name.
|
|
pszDescription - pointer to description string.
|
|
pszPrinters - pointer to printers using this port string.
|
|
|
|
Return Value:
|
|
|
|
TRUE port added to data list, FALSE error occurred.
|
|
|
|
--*/
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "PortsLV::AddPortDataList\n" ) );
|
|
|
|
//
|
|
// Allocate the port data.
|
|
//
|
|
TPortData *pPortData = new TPortData( pszName, pszMonitor, pszDescription, pszPrinters );
|
|
|
|
//
|
|
// If valid object created.
|
|
//
|
|
if( VALID_PTR( pPortData ) )
|
|
{
|
|
//
|
|
// Add the port data to the list.
|
|
//
|
|
PortDataList_vAppend( pPortData );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The object may have been allocated, however failed construction.
|
|
//
|
|
delete pPortData;
|
|
pPortData = NULL;
|
|
}
|
|
|
|
return pPortData;
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::
|
|
DeletePortDataList(
|
|
IN LPCTSTR pszName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete the specified port from the port data list.
|
|
|
|
Arguments:
|
|
|
|
pszName - pointer to port name.
|
|
|
|
Return Value:
|
|
|
|
TRUE port delete, FALSE error occurred.
|
|
|
|
--*/
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "PortsLV::DeletePortDataList\n" ) );
|
|
|
|
BOOL bStatus = FALSE;
|
|
TIter Iter;
|
|
|
|
for( PortDataList_vIterInit( Iter ), Iter.vNext(); Iter.bValid(); Iter.vNext() )
|
|
{
|
|
TPortData *pPortData = PortDataList_pConvert( Iter );
|
|
|
|
if( pPortData->_strName == pszName )
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "PortsLV::DeletePortDataList Port "TSTR" deleted\n", pszName ) );
|
|
delete pPortData;
|
|
bStatus = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return bStatus;
|
|
}
|
|
|
|
/********************************************************************
|
|
|
|
Port Data helper class.
|
|
|
|
********************************************************************/
|
|
|
|
TPortsLV::TPortData::
|
|
TPortData(
|
|
IN LPCTSTR pszName,
|
|
IN LPCTSTR pszMonitor,
|
|
IN LPCTSTR pszDescription,
|
|
IN LPCTSTR pszPrinters
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "PortsLV::TPortData ctor\n" ) );
|
|
_strName.bUpdate( pszName );
|
|
_strMonitor.bUpdate( pszMonitor );
|
|
_strDescription.bUpdate( pszDescription );
|
|
_strPrinters.bUpdate( pszPrinters );
|
|
}
|
|
|
|
TPortsLV::TPortData::
|
|
~TPortData(
|
|
VOID
|
|
)
|
|
{
|
|
DBGMSG( DBG_TRACE, ( "PortsLV::TPortData dtor\n" ) );
|
|
//
|
|
// If we are linked then remove ourself.
|
|
//
|
|
if( PortData_bLinked() )
|
|
{
|
|
PortData_vDelinkSelf();
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
TPortsLV::TPortData::
|
|
bValid(
|
|
VOID
|
|
)
|
|
{
|
|
return VALID_OBJ( _strName ) &&
|
|
VALID_OBJ( _strMonitor ) &&
|
|
VALID_OBJ( _strDescription ) &&
|
|
VALID_OBJ( _strPrinters );
|
|
|
|
}
|