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.
 
 
 
 
 
 

1519 lines
36 KiB

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corp., 1991 **/
/**********************************************************************/
/*
volumes.cxx
Class declarations for the VOLUMES_DIALOG, VOLUMES_LISTBOX, and
VOLUMES_LBI classes.
These classes implement the Server Manager Shared Volumes subproperty
sheet. The VOLUMES_LISTBOX/VOLUMES_LBI classes implement the listbox
which shows the available sharepoints. VOLUMES_DIALOG implements the
actual dialog box.
FILE HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
*/
#define INCL_NET
#define INCL_WINDOWS
#define INCL_WINDOWS_GDI
#define INCL_NETERRORS
#define INCL_DOSERRORS
#define INCL_NETLIB
#include <lmui.hxx>
#define INCL_BLT_WINDOW
#define INCL_BLT_DIALOG
#define INCL_BLT_CONTROL
#define INCL_BLT_MISC
#define INCL_BLT_CLIENT
#define INCL_BLT_MSGPOPUP
#include <blt.hxx>
#if defined(DEBUG)
static const CHAR szFileName[] = __FILE__;
#define _FILENAME_DEFINED_ONCE szFileName
#endif // DEBUG
#include <ellipsis.hxx>
#include <uiassert.hxx>
#include <ctime.hxx>
#include <intlprof.hxx>
extern "C"
{
#include <afpmgr.h>
#include <macfile.h>
} // extern "C"
#include <util.hxx>
#include <volumes.hxx>
//
// min/max macros
//
#define min(x,y) (((x) < (y)) ? (x) : (y))
#define max(x,y) (((x) > (y)) ? (x) : (y))
//
// VOLUMES_DIALOG methods.
//
/*******************************************************************
NAME: VOLUMES_DIALOG :: VOLUMES_DIALOG
SYNOPSIS: VOLUMES_DIALOG class constructor.
ENTRY: hWndOwner - The owning window.
hServer - Handle used to make admin
API calls.
pszServerName - Name of server currently
being administered.
EXIT: The object is constructed.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
VOLUMES_DIALOG :: VOLUMES_DIALOG( HWND hWndOwner,
AFP_SERVER_HANDLE hServer,
const TCHAR * pszServerName )
: DIALOG_WINDOW( MAKEINTRESOURCE( IDD_SHARED_VOLUMES ), hWndOwner ),
_hServer( hServer ),
_lbVolumes( this, IDSV_LB_VOLUMELIST, hServer ),
_lbUsers( this, IDSV_LB_USERLIST, hServer ),
_sltUsersCount( this, IDSV_DT_USERCOUNT ),
_pbDisconnect( this, IDSV_PB_DISCONNECT ),
_pbDisconnectAll( this, IDSV_PB_DISCONNECTALL ),
_pbOK( this, IDOK )
{
//
// Let's make sure everything constructed OK.
//
if( QueryError() != NERR_Success )
{
return;
}
APIERR err;
if ( (( err = _lbVolumes.QueryError() ) != NERR_Success ) ||
(( err = _lbUsers.QueryError() ) != NERR_Success ) ||
(( err = _sltUsersCount.QueryError() ) != NERR_Success ) ||
(( err = _pbDisconnect.QueryError() ) != NERR_Success ) ||
(( err = _pbDisconnectAll.QueryError() ) != NERR_Success ))
{
ReportError( err );
return;
}
//
// Just to be cool...
//
AUTO_CURSOR Cursor;
//
// Set the caption to "Shared Volumes on Server".
//
err = ::SetCaption( this, IDS_CAPTION_VOLUMES, pszServerName );
if( err != NERR_Success )
{
ReportError( err );
return;
}
err = BASE_ELLIPSIS::Init();
if( err != NO_ERROR )
{
ReportError( err );
return;
}
//
// Refresh the dialog.
//
err = Refresh();
if( err != NO_ERROR )
{
ReportError( AFPERR_TO_STRINGID( err ));
}
} // VOLUMES_DIALOG :: VOLUMES_DIALOG
/*******************************************************************
NAME: VOLUMES_DIALOG :: ~VOLUMES_DIALOG
SYNOPSIS: VOLUMES_DIALOG class destructor.
EXIT: The object is destroyed.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
VOLUMES_DIALOG :: ~VOLUMES_DIALOG()
{
BASE_ELLIPSIS::Term();
} // VOLUMES_DIALOG :: ~VOLUMES_DIALOG
/*******************************************************************
NAME: VOLUMES_DIALOG :: QueryHelpContext
SYNOPSIS: This function returns the appropriate help context
value (HC_*) for this particular dialog.
RETURNS: ULONG - The help context for this
dialog.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
ULONG VOLUMES_DIALOG :: QueryHelpContext( void )
{
return HC_VOLUMES_DIALOG;
} // VOLUMES_DIALOG :: QueryHelpContext
/*******************************************************************
NAME: VOLUMES_DIALOG :: OnCommand
SYNOPSIS: This method is called whenever a WM_COMMAND message
is sent to the dialog procedure.
ENTRY: cid - The control ID from the
generating control.
EXIT: The command has been handled.
RETURNS: BOOL - TRUE if we handled the command.
FALSE if we did not handle
the command.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
BOOL VOLUMES_DIALOG :: OnCommand( const CONTROL_EVENT & event )
{
DWORD err;
if( event.QueryCid() == _lbVolumes.QueryCid() )
{
//
// The VOLUMES_LISTBOX is trying to tell us something...
//
if( event.QueryCode() == LBN_SELCHANGE )
{
//
// The user changed the selection in the VOLUMES_LISTBOX.
//
VOLUMES_LBI * plbi = _lbVolumes.QueryItem();
UIASSERT( plbi != NULL );
_lbUsers.Refresh( plbi->QueryVolumeId() );
DWORD cUses = _lbUsers.QueryCount();
(VOID)plbi->NotifyNewUseCount( cUses );
_lbVolumes.InvalidateItem( _lbVolumes.QueryCurrentItem() );
_sltUsersCount.SetValue( cUses );
_pbDisconnect.Enable( cUses > 0 );
_pbDisconnectAll.Enable( cUses > 0 );
}
if ((event.QueryCode() == LBN_DBLCLK) && (_lbVolumes.QuerySelCount()>0))
{
VOLUMES_LBI * plbi = _lbVolumes.QueryItem();
::MsgPopup( this,
IDS_VOLUME_PATH,
MPSEV_INFO,
1,
plbi->QueryPath(),
MP_OK );
}
return TRUE;
}
if( event.QueryCid() == _pbDisconnect.QueryCid() )
{
//
// The user pressed the Disconnect button. Blow off the
// selected user.
//
USERS_LBI * pulbi = _lbUsers.QueryItem();
UIASSERT( pulbi != NULL );
VOLUMES_LBI * pvlbi = _lbVolumes.QueryItem();
UIASSERT( pvlbi != NULL );
if ( ::MsgPopup( this,
(pulbi->QueryNumOpens() > 0) ? IDS_DISCONNECT_VOL_OPEN
: IDS_DISCONNECT_VOL,
MPSEV_WARNING,
MP_YESNO,
pulbi->QueryUserName(),
pvlbi->QueryVolumeName(),
MP_NO ) == IDYES )
{
AUTO_CURSOR Cursor;
//
// Blow off the user.
//
err = ::AfpAdminConnectionClose( _hServer,
pulbi->QueryConnectionId() );
if( err != NO_ERROR )
{
//
// The session delete failed. Tell the user the bad news.
//
if ( err == AFPERR_InvalidId )
{
::MsgPopup( this, IDS_CONNECTION_DELETED );
}
else
{
::MsgPopup( this, AFPERR_TO_STRINGID( err ) );
}
}
//
// Refresh the dialog.
//
Refresh();
}
return TRUE;
}
if( event.QueryCid() == _pbDisconnectAll.QueryCid() )
{
//
// The user pressed the "Disconnect All" button.
// Blow off all of the connected users.
//
UIASSERT( _lbUsers.QueryCount() > 0 );
VOLUMES_LBI * pvlbi = _lbVolumes.QueryItem();
UIASSERT( pvlbi != NULL );
if( MsgPopup( this,
( _lbUsers.AreResourcesOpen() )
? IDS_DISCONNECT_VOL_ALL_OPEN
: IDS_DISCONNECT_VOL_ALL,
MPSEV_WARNING,
MP_YESNO,
pvlbi->QueryVolumeName(),
MP_NO ) == IDYES )
{
AUTO_CURSOR Cursor;
INT nCount = _lbUsers.QueryCount();
for ( INT Index = 0; Index < nCount; Index++ )
{
USERS_LBI * pulbi = _lbUsers.QueryItem( Index );
//
// Blow away this connection
//
err = :: AfpAdminConnectionClose( _hServer,
pulbi->QueryConnectionId() );
if ( ( err != NO_ERROR ) && ( err != AFPERR_InvalidId ) )
{
break;
}
}
if( ( err != NO_ERROR ) && ( err != AFPERR_InvalidId ) )
{
//
// The connection delete failed.
// Tell the user the bad news.
//
MsgPopup( this, AFPERR_TO_STRINGID(err) );
}
//
// Refresh the dialog.
//
Refresh();
}
return TRUE;
}
//
// If we made it this far, then we're not
// interested in the command.
//
return FALSE;
} // VOLUMES_DIALOG :: OnCommand
/*******************************************************************
NAME: VOLUMES_DIALOG :: Refresh
SYNOPSIS: Refresh the dialog.
EXIT: The dialog is feeling refreshed.
RETURNS: DWORD - Any errors encountered.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
DWORD VOLUMES_DIALOG :: Refresh( VOID )
{
//
// This is the currently selected item.
//
VOLUMES_LBI * plbiOld = _lbVolumes.QueryItem();
DWORD dwVolumeIdOld = ( plbiOld == NULL ) ? 0 : plbiOld->QueryVolumeId();
//
// Refresh the resource listbox.
//
DWORD err = _lbVolumes.Refresh();
if( err != NO_ERROR )
{
//
// There was an error refreshing the resource listbox.
// So, nuke everything in the volumes & user listboxen,
// then disable the Disconnect[All] buttons.
//
_lbVolumes.DeleteAllItems();
_lbVolumes.Invalidate( TRUE );
_lbUsers.DeleteAllItems();
_lbUsers.Invalidate( TRUE );
_pbDisconnect.Enable( FALSE );
_pbDisconnectAll.Enable( FALSE );
return err;
}
//
// Get the "new" currently selected item (after the refresh).
//
VOLUMES_LBI * plbiNew = _lbVolumes.QueryItem();
DWORD dwVolumeIdNew = (plbiNew == NULL) ? 0 : plbiNew->QueryVolumeId();
if( plbiNew == NULL )
{
//
// There is no current selection, so clear the users listbox.
//
err = _lbUsers.Refresh( 0 );
}
else
if( ( plbiOld == NULL ) || ( dwVolumeIdOld != dwVolumeIdNew ) )
{
//
// Either there was no selection before the refresh, OR
// the current selection does not match the previous
// selection. Therefore, fill the users listbox with
// the current selection.
//
err = _lbUsers.Refresh( plbiNew->QueryVolumeId() );
}
else
{
//
// There was no selection change after refresh. Therefore,
// refresh the users listbox.
//
err = _lbUsers.Refresh( plbiNew->QueryVolumeId() );
}
if ( _lbUsers.QuerySelCount() > 0 )
{
_pbDisconnect.Enable( TRUE );
}
else
{
if ( _pbDisconnect.HasFocus() )
{
_pbOK.ClaimFocus();
}
_pbDisconnect.Enable( FALSE );
}
if ( _lbUsers.QueryCount() > 0 )
{
_pbDisconnectAll.Enable( TRUE );
}
else
{
if ( _pbDisconnectAll.HasFocus() )
{
_pbOK.ClaimFocus();
}
_pbDisconnectAll.Enable( FALSE );
}
_sltUsersCount.SetValue( _lbUsers.QueryCount() );
//
// Success!
//
return err;
} // VOLUMES_DIALOG :: Refresh
//
// VOLUMES_LISTBOX methods.
//
/*******************************************************************
NAME: VOLUMES_LISTBOX :: VOLUMES_LISTBOX
SYNOPSIS: VOLUMEs_LISTBOX class constructor.
ENTRY: powOwner - The owning window.
cid - The listbox CID.
hServer - The target server.
EXIT: The object is constructed.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
VOLUMES_LISTBOX :: VOLUMES_LISTBOX( OWNER_WINDOW * powOwner,
CID cid,
AFP_SERVER_HANDLE hServer )
: BLT_LISTBOX( powOwner, cid ),
_hServer( hServer ),
_dteDisk( IDBM_LB_GOOD_VOLUME )
{
//
// Ensure we constructed properly.
//
if( QueryError() != NERR_Success )
{
return;
}
APIERR err;
if( ( err = _dteDisk.QueryError() ) != NERR_Success )
{
ReportError( err );
return;
}
//
// Build our column width table.
//
DISPLAY_TABLE::CalcColumnWidths( _adx,
COLS_SV_LB_VOLUMES,
powOwner,
cid,
TRUE ) ;
} // VOLUMES_LISTBOX :: VOLUMES_LISTBOX
/*******************************************************************
NAME: VOLUMES_LISTBOX :: ~VOLUMES_LISTBOX
SYNOPSIS: VOLUMES_LISTBOX class destructor.
EXIT: The object is destroyed.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
VOLUMES_LISTBOX :: ~VOLUMES_LISTBOX()
{
//
// This space intentionally left blank.
//
} // VOLUMES_LISTBOX :: ~VOLUMES_LISTBOX
/*******************************************************************
NAME: VOLUMES_LISTBOX :: Refresh
SYNOPSIS: Refresh the listbox, maintaining (as much as
possible) the current selection state.
EXIT: The listbox is feeling refreshed.
RETURNS: DWORD - Any errors we encounter.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
DWORD VOLUMES_LISTBOX :: Refresh( VOID )
{
INT iCurrent = QueryCurrentItem();
INT iTop = QueryTopIndex();
DWORD dwCurrentVolumeId = 0;
//
// Retrieve the volume id of the current selection
//
if ( QuerySelCount() > 0 )
{
dwCurrentVolumeId = QueryItem( iCurrent )->QueryVolumeId();
}
DWORD err = Fill();
if( err != NO_ERROR )
{
return err;
}
INT cItems = QueryCount();
if( cItems > 0 )
{
INT iSel = -1;
if ( ( iCurrent >= 0 ) && ( iCurrent < cItems ) )
{
//
// iCurrent is still valid, see if this item matches the
// pre-refresh item.
//
if ( dwCurrentVolumeId == QueryItem( iCurrent )->QueryVolumeId() )
{
iSel = iCurrent;
}
}
if ( iSel < 0 )
{
//
// Either iCurrent was out of range or the item does not
// match so search for it.
//
for ( INT i = 0; i < cItems; i++ )
{
VOLUMES_LBI * plbi = QueryItem( i );
if ( dwCurrentVolumeId == plbi->QueryVolumeId() )
{
iSel = i;
break;
}
}
}
if ( iSel < 0 )
{
//
// If no selection found then default = first item
//
iSel = 0;
}
//
// If the previous top index is out of range then
// set default = first item.
//
if ( ( iTop < 0 ) || ( iTop >= cItems ) )
{
iTop = 0;
}
SetTopIndex( iTop );
SelectItem( iSel );
}
return NO_ERROR;
} // VOLUMES_LISTBOX :: Refresh
/*******************************************************************
NAME: VOLUMES_LISTBOX :: Fill
SYNOPSIS: Fills the listbox with the available sharepoints.
EXIT: The listbox is filled.
RETURNS: DWORD - Any errors encountered.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
DWORD VOLUMES_LISTBOX :: Fill( VOID )
{
//
// Just to be cool...
//
AUTO_CURSOR Cursor;
//
// Enumerate all successfully shared volumes.
//
PAFP_VOLUME_INFO pAfpVolumes;
DWORD cEntriesRead;
DWORD cTotalAvail;
DWORD err = ::AfpAdminVolumeEnum( _hServer,
(LPBYTE*)&pAfpVolumes,
(DWORD)-1, // Get all volumes
&cEntriesRead,
&cTotalAvail,
NULL );
//
// See if the volumes are available.
//
if( err != NO_ERROR )
{
return err;
}
//
// Now that we know the volume info is available,
// let's nuke everything in the listbox.
//
SetRedraw( FALSE );
DeleteAllItems();
//
// For iterating the available sharepoints.
//
PAFP_VOLUME_INFO pVolIter = pAfpVolumes;
//
// Iterate the volumes adding them to the listbox.
//
err = NO_ERROR;
while( ( err == NO_ERROR ) && ( cEntriesRead-- ) )
{
VOLUMES_LBI * pslbi = new VOLUMES_LBI( pVolIter->afpvol_id,
pVolIter->afpvol_name,
pVolIter->afpvol_path,
pVolIter->afpvol_curr_uses,
&_dteDisk );
if( AddItem( pslbi ) < 0 )
{
//
// CODEWORK: What should we do in error conditions?
// As currently spec'd, we do nothing. If the data
// cannot be retrieved, we display "n/a" in the
// statistics strings. Should we hide the listbox
// and display a message a'la WINNET??
//
err = ERROR_NOT_ENOUGH_MEMORY;
}
pVolIter++;
}
::AfpAdminBufferFree( pAfpVolumes );
SetRedraw( TRUE );
Invalidate( TRUE );
return err;
} // VOLUMES_LISTBOX :: Fill
//
// VOLUMES_LBI methods.
//
/*******************************************************************
NAME: VOLUMES_LBI :: VOLUMES_LBI
SYNOPSIS: VOLUMES_LBI class constructor.
ENTRY: pszVolumeName - The sharepoint name.
pszPath - The path for this sharepoint.
cUses - Number of uses for this share.
EXIT: The object is constructed.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
VOLUMES_LBI :: VOLUMES_LBI( DWORD dwVolumeId,
const TCHAR * pszVolumeName,
const TCHAR * pszPath,
DWORD cUses,
DMID_DTE * pdte )
: _dwVolumeId( dwVolumeId ),
_nlsVolumeName( pszVolumeName ),
_pdte( pdte ),
_nlsPath( pszPath ),
_nlsUses( cUses )
{
UIASSERT( pszVolumeName != NULL );
UIASSERT( pdte != NULL );
//
// Ensure we constructed properly.
//
if( QueryError() != NERR_Success )
{
return;
}
APIERR err;
if( ( ( err = _nlsPath.QueryError() ) != NERR_Success ) ||
( ( err = _nlsUses.QueryError() ) != NERR_Success ) ||
( ( err = _nlsVolumeName.QueryError() ) != NERR_Success ) )
{
ReportError( err );
return;
}
} // VOLUMES_LBI :: VOLUMES_LBI
/*******************************************************************
NAME: VOLUMES_LBI :: ~VOLUMES_LBI
SYNOPSIS: VOLUMES_LBI class destructor.
EXIT: The object is destroyed.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
VOLUMES_LBI :: ~VOLUMES_LBI()
{
_pdte = NULL;
} // VOLUMES_LBI :: ~VOLUMES_LBI
/*******************************************************************
NAME: VOLUMES_LBI :: Paint
SYNOPSIS: Draw an entry in VOLUMES_LISTBOX.
ENTRY: plb - Pointer to a BLT_LISTBOX.
hdc - The DC to draw upon.
prect - Clipping rectangle.
pGUILTT - GUILTT info.
EXIT: The item is drawn.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
VOID VOLUMES_LBI :: Paint( LISTBOX * plb,
HDC hdc,
const RECT * prect,
GUILTT_INFO * pGUILTT ) const
{
STR_DTE_ELLIPSIS dteVolumeName( _nlsVolumeName.QueryPch(),
plb, ELLIPSIS_RIGHT );
STR_DTE dteUses( _nlsUses.QueryPch() );
STR_DTE_ELLIPSIS dtePath( _nlsPath.QueryPch(), plb, ELLIPSIS_PATH );
DISPLAY_TABLE dtab( COLS_SV_LB_VOLUMES,
((VOLUMES_LISTBOX *)plb)->QueryColumnWidths() );
dtab[0] = _pdte;
dtab[1] = &dteVolumeName;
dtab[2] = &dteUses;
dtab[3] = &dtePath;
dtab.Paint( plb, hdc, prect, pGUILTT );
} // VOLUMES_LBI :: Paint
/*******************************************************************
NAME: VOLUMES_LBI :: NotifyNewUseCount
SYNOPSIS: Notifies the LBI that the "use" count has changed.
ENTRY: cUses - The new use count.
RETURNS: DWORD - Any errors that occur.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
APIERR VOLUMES_LBI :: NotifyNewUseCount( DWORD cUses )
{
DEC_STR nls( cUses );
APIERR err = nls.QueryError();
if( err == NERR_Success )
{
err = _nlsUses.CopyFrom( nls );
}
return err;
} // VOLUMES_LBI :: NotifyNewUseCount
/*******************************************************************
NAME: VOLUMES_LBI :: QueryLeadingChar
SYNOPSIS: Returns the first character in the resource name.
This is used for the listbox keyboard interface.
RETURNS: WCHAR - The first character in the
resource name.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
WCHAR VOLUMES_LBI :: QueryLeadingChar( VOID ) const
{
ISTR istr( _nlsVolumeName );
return _nlsVolumeName.QueryChar( istr );
} // VOLUMES_LBI :: QueryLeadingChar
/*******************************************************************
NAME: VOLUMES_LBI :: Compare
SYNOPSIS: Compare two BASE_RES_LBI items.
ENTRY: plbi - The LBI to compare against.
RETURNS: INT - The result of the compare
( <0 , ==0 , >0 ).
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
INT VOLUMES_LBI :: Compare( const LBI * plbi ) const
{
return _nlsVolumeName._stricmp( ((const VOLUMES_LBI *)plbi)->_nlsVolumeName);
} // VOLUMES_LBI :: Compare
//
// USERS_LISTBOX methods.
//
/*******************************************************************
NAME: USERS_LISTBOX :: USERS_LISTBOX
SYNOPSIS: USERS_LISTBOX class constructor.
ENTRY: powner - The owning window.
cid - The listbox CID.
hServer - Handlr to the remote server.
EXIT: The object is constructed.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
USERS_LISTBOX :: USERS_LISTBOX( OWNER_WINDOW * powner,
CID cid,
AFP_SERVER_HANDLE hServer )
: BLT_LISTBOX( powner, cid ),
_hServer( hServer ),
_dteIcon( IDBM_LB_USER )
{
//
// Make sure everything constructed properly.
//
if( QueryError() != NERR_Success )
{
return;
}
APIERR err;
if( ( err = _dteIcon.QueryError() ) != NERR_Success )
{
ReportError( err );
return;
}
//
// Retrieve the time separator.
//
NLS_STR nlsTimeSep;
if( ( err = nlsTimeSep.QueryError() ) != NERR_Success )
{
ReportError( err );
return;
}
INTL_PROFILE intl;
if( ( err = intl.QueryError() ) != NERR_Success )
{
ReportError( intl.QueryError() );
return;
}
if ( ( err = intl.QueryTimeSeparator( &nlsTimeSep ) ) != NERR_Success )
{
ReportError( err );
return;
}
UIASSERT( nlsTimeSep.QueryTextLength() == 1 );
_chTimeSep = *(nlsTimeSep.QueryPch());
//
// Build the column width table used for
// displaying the listbox items.
//
DISPLAY_TABLE::CalcColumnWidths( _adx,
COLS_SV_LB_USERS,
powner,
cid,
TRUE) ;
} // USERS_LISTBOX :: USERS_LISTBOX
/*******************************************************************
NAME: USERS_LISTBOX :: ~USERS_LISTBOX
SYNOPSIS: USERS_LISTBOX class destructor.
EXIT: The object is destroyed.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
USERS_LISTBOX :: ~USERS_LISTBOX()
{
//
// This space intentionally left blank.
//
} // USERS_LISTBOX :: ~USERS_LISTBOX
/*******************************************************************
NAME: USERS_LISTBOX :: Fill
SYNOPSIS: Fills the listbox with the connected users.
ENTRY: pszShare - The target sharename. Note
that this sharename is "sticky"
in that it will be used in
subsequent Refresh() calls.
EXIT: The listbox is filled.
RETURNS: APIERR - Any errors encountered.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
DWORD USERS_LISTBOX :: Fill( DWORD dwVolumeId )
{
//
// Just to be cool...
//
AUTO_CURSOR Cursor;
//
// Nuke the listbox.
//
DeleteAllItems();
//
// If the Volume Id is zero (a valid scenario) then
// there are no connections in the listbox.
//
if( dwVolumeId == 0 )
{
return NO_ERROR;
}
//
// Enumerate the connections to this volume.
//
PAFP_CONNECTION_INFO pAfpConnections;
DWORD cEntriesRead;
DWORD cTotalAvail;
DWORD err = ::AfpAdminConnectionEnum( _hServer,
(LPBYTE*)&pAfpConnections,
AFP_FILTER_ON_VOLUME_ID,
dwVolumeId,
(DWORD)-1, // Get all conenctions
&cEntriesRead,
&cTotalAvail,
NULL );
//
// See if the connections are available.
//
if( err != NO_ERROR )
{
return err;
}
SetRedraw( FALSE );
//
// For iterating the available connections.
//
PAFP_CONNECTION_INFO pConnIter = pAfpConnections;
//
// Iterate the connections adding them to the listbox.
//
while( ( err == NO_ERROR ) && ( cEntriesRead-- ) )
{
USERS_LBI * pclbi = new USERS_LBI( pConnIter->afpconn_id,
pConnIter->afpconn_username,
pConnIter->afpconn_time,
pConnIter->afpconn_num_opens,
_chTimeSep,
&_dteIcon );
if( AddItem( pclbi ) < 0 )
{
err = ERROR_NOT_ENOUGH_MEMORY;
}
pConnIter++;
}
::AfpAdminBufferFree( pAfpConnections );
SetRedraw( TRUE );
Invalidate( TRUE );
return err;
} // USERS_LISTBOX :: Fill
/*******************************************************************
NAME: USERS_LISTBOX :: Refresh
SYNOPSIS: Refreshes the listbox, maintaining (as much as
possible) the relative position of the current
selection.
EXIT: The listbox is feeling refreshed.
RETURNS: DWORD - Any errors encountered.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
DWORD USERS_LISTBOX :: Refresh( DWORD dwVolumeId )
{
INT iCurrent = QueryCurrentItem();
INT iTop = QueryTopIndex();
DWORD err = Fill( dwVolumeId );
if( err != NO_ERROR )
{
return err;
}
INT cItems = QueryCount();
if( cItems > 0 )
{
iCurrent = min( max( iCurrent, 0 ), cItems - 1 );
iTop = min( max( iTop, 0 ), cItems - 1 );
SelectItem( iCurrent );
SetTopIndex( iTop );
}
return NO_ERROR;
} // USERS_LISTBOX :: Refresh
/*******************************************************************
NAME: USERS_LISTBOX :: AreResourcesOpen
SYNOPSIS: Returns TRUE if any user in the listbox has any
resources open.
RETURNS: BOOL
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
BOOL USERS_LISTBOX :: AreResourcesOpen( VOID ) const
{
INT cItems = QueryCount();
for( INT i = 0 ; i < cItems ; i++ )
{
USERS_LBI * plbi = QueryItem( i );
if( plbi->QueryNumOpens() > 0 )
{
return TRUE;
}
}
return FALSE;
} // USERS_LISTBOX :: AreResourcesOpen
//
// USERS_LBI methods.
//
/*******************************************************************
NAME: USERS_LBI :: USERS_LBI
SYNOPSIS: USERS_LBI class constructor.
ENTRY: pszUserName - The user for this entry.
pszComputerName - The user's computer name.
ulTime - Connection time.
cOpens - Number of opens on this connection.
chTimeSep - Time format separator.
EXIT: The object is constructed.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
USERS_LBI :: USERS_LBI( DWORD dwConnectionId,
const TCHAR * pszUserName,
ULONG ulTime,
DWORD cOpens,
TCHAR chTimeSep,
DMID_DTE * pdte )
: _dwConnectionId( dwConnectionId ),
_nlsInUse(),
_nlsUserName(),
_nlsTime( ulTime, chTimeSep ),
_pdte( pdte ),
_cOpens( cOpens )
{
//
// Make sure everything constructed properly.
//
if( QueryError() != NERR_Success )
{
return;
}
APIERR err;
if( ( ( err = _nlsUserName.QueryError() ) != NERR_Success ) ||
( ( err = _nlsInUse.QueryError() ) != NERR_Success ) ||
( ( err = _nlsTime.QueryError() ) != NERR_Success ) )
{
ReportError( err );
return;
}
//
// Build the more complex display strings.
//
err = _nlsInUse.Load( ( cOpens > 0 ) ? IDS_YES : IDS_NO );
if ( err == NERR_Success )
{
if ( pszUserName == NULL )
{
err = _nlsUserName.Load( IDS_GUEST );
}
else
{
err = _nlsUserName.CopyFrom( pszUserName );
}
}
if( err != NERR_Success )
{
ReportError( err );
return;
}
} // USERS_LBI :: USERS_LBI
/*******************************************************************
NAME: USERS_LBI :: ~USERS_LBI
SYNOPSIS: USERS_LBI class destructor.
EXIT: The object is destroyed.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
USERS_LBI :: ~USERS_LBI()
{
//
// This space intentionally left blank.
//
} // USERS_LBI :: ~USERS_LBI
/*******************************************************************
NAME: USERS_LBI :: Paint
SYNOPSIS: Draw an entry in USERS_LISTBOX.
ENTRY: plb - Pointer to a BLT_LISTBOX.
hdc - The DC to draw upon.
prect - Clipping rectangle.
pGUILTT - GUILTT info.
EXIT: The item is drawn.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
VOID USERS_LBI :: Paint( LISTBOX * plb,
HDC hdc,
const RECT * prect,
GUILTT_INFO * pGUILTT ) const
{
STR_DTE_ELLIPSIS dteUserName( _nlsUserName.QueryPch(),
plb, ELLIPSIS_RIGHT );
STR_DTE dteTime( _nlsTime.QueryPch() );
STR_DTE dteInUse( _nlsInUse.QueryPch() );
DISPLAY_TABLE dtab( COLS_SV_LB_USERS,
((USERS_LISTBOX *)plb)->QueryColumnWidths() );
dtab[0] = _pdte;
dtab[1] = &dteUserName;
dtab[2] = &dteTime;
dtab[3] = &dteInUse;
dtab.Paint( plb, hdc, prect, pGUILTT );
} // USERS_LBI :: Paint
/*******************************************************************
NAME: USERS_LBI :: QueryLeadingChar
SYNOPSIS: Return the leading character of this item.
RETURNS: WCHAR - The leading character.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
WCHAR USERS_LBI :: QueryLeadingChar( VOID ) const
{
ISTR istr( _nlsUserName );
return _nlsUserName.QueryChar( istr );
} // USERS_LBI :: QueryLeadingChar
/*******************************************************************
NAME: USERS_LBI :: Compare
SYNOPSIS: Compare two USERS_LBI items.
ENTRY: plbi - The "other" item.
RETURNS: INT - 0 if the items match.
-1 if we're < the other item.
+1 if we're > the other item.
HISTORY:
NarenG 02-Oct-1993 Stole from Server Manager and folded
BASE_RES_DIALOG and FILES_DIALOG into one.
********************************************************************/
INT USERS_LBI :: Compare( const LBI * plbi ) const
{
NLS_STR * pnls = &(((USERS_LBI *)plbi)->_nlsUserName);
return _nlsUserName._stricmp( *pnls );
} // USERS_LBI :: Compare