/**********************************************************************/ /** 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 #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 #if defined(DEBUG) static const CHAR szFileName[] = __FILE__; #define _FILENAME_DEFINED_ONCE szFileName #endif // DEBUG #include #include #include #include extern "C" { #include #include } // extern "C" #include #include // // 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