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

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corp., 1991 **/
  4. /**********************************************************************/
  5. /*
  6. volumes.cxx
  7. Class declarations for the VOLUMES_DIALOG, VOLUMES_LISTBOX, and
  8. VOLUMES_LBI classes.
  9. These classes implement the Server Manager Shared Volumes subproperty
  10. sheet. The VOLUMES_LISTBOX/VOLUMES_LBI classes implement the listbox
  11. which shows the available sharepoints. VOLUMES_DIALOG implements the
  12. actual dialog box.
  13. FILE HISTORY:
  14. NarenG 02-Oct-1993 Stole from Server Manager and folded
  15. BASE_RES_DIALOG and FILES_DIALOG into one.
  16. */
  17. #define INCL_NET
  18. #define INCL_WINDOWS
  19. #define INCL_WINDOWS_GDI
  20. #define INCL_NETERRORS
  21. #define INCL_DOSERRORS
  22. #define INCL_NETLIB
  23. #include <lmui.hxx>
  24. #define INCL_BLT_WINDOW
  25. #define INCL_BLT_DIALOG
  26. #define INCL_BLT_CONTROL
  27. #define INCL_BLT_MISC
  28. #define INCL_BLT_CLIENT
  29. #define INCL_BLT_MSGPOPUP
  30. #include <blt.hxx>
  31. #if defined(DEBUG)
  32. static const CHAR szFileName[] = __FILE__;
  33. #define _FILENAME_DEFINED_ONCE szFileName
  34. #endif // DEBUG
  35. #include <ellipsis.hxx>
  36. #include <uiassert.hxx>
  37. #include <ctime.hxx>
  38. #include <intlprof.hxx>
  39. extern "C"
  40. {
  41. #include <afpmgr.h>
  42. #include <macfile.h>
  43. } // extern "C"
  44. #include <util.hxx>
  45. #include <volumes.hxx>
  46. //
  47. // min/max macros
  48. //
  49. #define min(x,y) (((x) < (y)) ? (x) : (y))
  50. #define max(x,y) (((x) > (y)) ? (x) : (y))
  51. //
  52. // VOLUMES_DIALOG methods.
  53. //
  54. /*******************************************************************
  55. NAME: VOLUMES_DIALOG :: VOLUMES_DIALOG
  56. SYNOPSIS: VOLUMES_DIALOG class constructor.
  57. ENTRY: hWndOwner - The owning window.
  58. hServer - Handle used to make admin
  59. API calls.
  60. pszServerName - Name of server currently
  61. being administered.
  62. EXIT: The object is constructed.
  63. HISTORY:
  64. NarenG 02-Oct-1993 Stole from Server Manager and folded
  65. BASE_RES_DIALOG and FILES_DIALOG into one.
  66. ********************************************************************/
  67. VOLUMES_DIALOG :: VOLUMES_DIALOG( HWND hWndOwner,
  68. AFP_SERVER_HANDLE hServer,
  69. const TCHAR * pszServerName )
  70. : DIALOG_WINDOW( MAKEINTRESOURCE( IDD_SHARED_VOLUMES ), hWndOwner ),
  71. _hServer( hServer ),
  72. _lbVolumes( this, IDSV_LB_VOLUMELIST, hServer ),
  73. _lbUsers( this, IDSV_LB_USERLIST, hServer ),
  74. _sltUsersCount( this, IDSV_DT_USERCOUNT ),
  75. _pbDisconnect( this, IDSV_PB_DISCONNECT ),
  76. _pbDisconnectAll( this, IDSV_PB_DISCONNECTALL ),
  77. _pbOK( this, IDOK )
  78. {
  79. //
  80. // Let's make sure everything constructed OK.
  81. //
  82. if( QueryError() != NERR_Success )
  83. {
  84. return;
  85. }
  86. APIERR err;
  87. if ( (( err = _lbVolumes.QueryError() ) != NERR_Success ) ||
  88. (( err = _lbUsers.QueryError() ) != NERR_Success ) ||
  89. (( err = _sltUsersCount.QueryError() ) != NERR_Success ) ||
  90. (( err = _pbDisconnect.QueryError() ) != NERR_Success ) ||
  91. (( err = _pbDisconnectAll.QueryError() ) != NERR_Success ))
  92. {
  93. ReportError( err );
  94. return;
  95. }
  96. //
  97. // Just to be cool...
  98. //
  99. AUTO_CURSOR Cursor;
  100. //
  101. // Set the caption to "Shared Volumes on Server".
  102. //
  103. err = ::SetCaption( this, IDS_CAPTION_VOLUMES, pszServerName );
  104. if( err != NERR_Success )
  105. {
  106. ReportError( err );
  107. return;
  108. }
  109. err = BASE_ELLIPSIS::Init();
  110. if( err != NO_ERROR )
  111. {
  112. ReportError( err );
  113. return;
  114. }
  115. //
  116. // Refresh the dialog.
  117. //
  118. err = Refresh();
  119. if( err != NO_ERROR )
  120. {
  121. ReportError( AFPERR_TO_STRINGID( err ));
  122. }
  123. } // VOLUMES_DIALOG :: VOLUMES_DIALOG
  124. /*******************************************************************
  125. NAME: VOLUMES_DIALOG :: ~VOLUMES_DIALOG
  126. SYNOPSIS: VOLUMES_DIALOG class destructor.
  127. EXIT: The object is destroyed.
  128. HISTORY:
  129. NarenG 02-Oct-1993 Stole from Server Manager and folded
  130. BASE_RES_DIALOG and FILES_DIALOG into one.
  131. ********************************************************************/
  132. VOLUMES_DIALOG :: ~VOLUMES_DIALOG()
  133. {
  134. BASE_ELLIPSIS::Term();
  135. } // VOLUMES_DIALOG :: ~VOLUMES_DIALOG
  136. /*******************************************************************
  137. NAME: VOLUMES_DIALOG :: QueryHelpContext
  138. SYNOPSIS: This function returns the appropriate help context
  139. value (HC_*) for this particular dialog.
  140. RETURNS: ULONG - The help context for this
  141. dialog.
  142. HISTORY:
  143. NarenG 02-Oct-1993 Stole from Server Manager and folded
  144. BASE_RES_DIALOG and FILES_DIALOG into one.
  145. ********************************************************************/
  146. ULONG VOLUMES_DIALOG :: QueryHelpContext( void )
  147. {
  148. return HC_VOLUMES_DIALOG;
  149. } // VOLUMES_DIALOG :: QueryHelpContext
  150. /*******************************************************************
  151. NAME: VOLUMES_DIALOG :: OnCommand
  152. SYNOPSIS: This method is called whenever a WM_COMMAND message
  153. is sent to the dialog procedure.
  154. ENTRY: cid - The control ID from the
  155. generating control.
  156. EXIT: The command has been handled.
  157. RETURNS: BOOL - TRUE if we handled the command.
  158. FALSE if we did not handle
  159. the command.
  160. HISTORY:
  161. NarenG 02-Oct-1993 Stole from Server Manager and folded
  162. BASE_RES_DIALOG and FILES_DIALOG into one.
  163. ********************************************************************/
  164. BOOL VOLUMES_DIALOG :: OnCommand( const CONTROL_EVENT & event )
  165. {
  166. DWORD err;
  167. if( event.QueryCid() == _lbVolumes.QueryCid() )
  168. {
  169. //
  170. // The VOLUMES_LISTBOX is trying to tell us something...
  171. //
  172. if( event.QueryCode() == LBN_SELCHANGE )
  173. {
  174. //
  175. // The user changed the selection in the VOLUMES_LISTBOX.
  176. //
  177. VOLUMES_LBI * plbi = _lbVolumes.QueryItem();
  178. UIASSERT( plbi != NULL );
  179. _lbUsers.Refresh( plbi->QueryVolumeId() );
  180. DWORD cUses = _lbUsers.QueryCount();
  181. (VOID)plbi->NotifyNewUseCount( cUses );
  182. _lbVolumes.InvalidateItem( _lbVolumes.QueryCurrentItem() );
  183. _sltUsersCount.SetValue( cUses );
  184. _pbDisconnect.Enable( cUses > 0 );
  185. _pbDisconnectAll.Enable( cUses > 0 );
  186. }
  187. if ((event.QueryCode() == LBN_DBLCLK) && (_lbVolumes.QuerySelCount()>0))
  188. {
  189. VOLUMES_LBI * plbi = _lbVolumes.QueryItem();
  190. ::MsgPopup( this,
  191. IDS_VOLUME_PATH,
  192. MPSEV_INFO,
  193. 1,
  194. plbi->QueryPath(),
  195. MP_OK );
  196. }
  197. return TRUE;
  198. }
  199. if( event.QueryCid() == _pbDisconnect.QueryCid() )
  200. {
  201. //
  202. // The user pressed the Disconnect button. Blow off the
  203. // selected user.
  204. //
  205. USERS_LBI * pulbi = _lbUsers.QueryItem();
  206. UIASSERT( pulbi != NULL );
  207. VOLUMES_LBI * pvlbi = _lbVolumes.QueryItem();
  208. UIASSERT( pvlbi != NULL );
  209. if ( ::MsgPopup( this,
  210. (pulbi->QueryNumOpens() > 0) ? IDS_DISCONNECT_VOL_OPEN
  211. : IDS_DISCONNECT_VOL,
  212. MPSEV_WARNING,
  213. MP_YESNO,
  214. pulbi->QueryUserName(),
  215. pvlbi->QueryVolumeName(),
  216. MP_NO ) == IDYES )
  217. {
  218. AUTO_CURSOR Cursor;
  219. //
  220. // Blow off the user.
  221. //
  222. err = ::AfpAdminConnectionClose( _hServer,
  223. pulbi->QueryConnectionId() );
  224. if( err != NO_ERROR )
  225. {
  226. //
  227. // The session delete failed. Tell the user the bad news.
  228. //
  229. if ( err == AFPERR_InvalidId )
  230. {
  231. ::MsgPopup( this, IDS_CONNECTION_DELETED );
  232. }
  233. else
  234. {
  235. ::MsgPopup( this, AFPERR_TO_STRINGID( err ) );
  236. }
  237. }
  238. //
  239. // Refresh the dialog.
  240. //
  241. Refresh();
  242. }
  243. return TRUE;
  244. }
  245. if( event.QueryCid() == _pbDisconnectAll.QueryCid() )
  246. {
  247. //
  248. // The user pressed the "Disconnect All" button.
  249. // Blow off all of the connected users.
  250. //
  251. UIASSERT( _lbUsers.QueryCount() > 0 );
  252. VOLUMES_LBI * pvlbi = _lbVolumes.QueryItem();
  253. UIASSERT( pvlbi != NULL );
  254. if( MsgPopup( this,
  255. ( _lbUsers.AreResourcesOpen() )
  256. ? IDS_DISCONNECT_VOL_ALL_OPEN
  257. : IDS_DISCONNECT_VOL_ALL,
  258. MPSEV_WARNING,
  259. MP_YESNO,
  260. pvlbi->QueryVolumeName(),
  261. MP_NO ) == IDYES )
  262. {
  263. AUTO_CURSOR Cursor;
  264. INT nCount = _lbUsers.QueryCount();
  265. for ( INT Index = 0; Index < nCount; Index++ )
  266. {
  267. USERS_LBI * pulbi = _lbUsers.QueryItem( Index );
  268. //
  269. // Blow away this connection
  270. //
  271. err = :: AfpAdminConnectionClose( _hServer,
  272. pulbi->QueryConnectionId() );
  273. if ( ( err != NO_ERROR ) && ( err != AFPERR_InvalidId ) )
  274. {
  275. break;
  276. }
  277. }
  278. if( ( err != NO_ERROR ) && ( err != AFPERR_InvalidId ) )
  279. {
  280. //
  281. // The connection delete failed.
  282. // Tell the user the bad news.
  283. //
  284. MsgPopup( this, AFPERR_TO_STRINGID(err) );
  285. }
  286. //
  287. // Refresh the dialog.
  288. //
  289. Refresh();
  290. }
  291. return TRUE;
  292. }
  293. //
  294. // If we made it this far, then we're not
  295. // interested in the command.
  296. //
  297. return FALSE;
  298. } // VOLUMES_DIALOG :: OnCommand
  299. /*******************************************************************
  300. NAME: VOLUMES_DIALOG :: Refresh
  301. SYNOPSIS: Refresh the dialog.
  302. EXIT: The dialog is feeling refreshed.
  303. RETURNS: DWORD - Any errors encountered.
  304. HISTORY:
  305. NarenG 02-Oct-1993 Stole from Server Manager and folded
  306. BASE_RES_DIALOG and FILES_DIALOG into one.
  307. ********************************************************************/
  308. DWORD VOLUMES_DIALOG :: Refresh( VOID )
  309. {
  310. //
  311. // This is the currently selected item.
  312. //
  313. VOLUMES_LBI * plbiOld = _lbVolumes.QueryItem();
  314. DWORD dwVolumeIdOld = ( plbiOld == NULL ) ? 0 : plbiOld->QueryVolumeId();
  315. //
  316. // Refresh the resource listbox.
  317. //
  318. DWORD err = _lbVolumes.Refresh();
  319. if( err != NO_ERROR )
  320. {
  321. //
  322. // There was an error refreshing the resource listbox.
  323. // So, nuke everything in the volumes & user listboxen,
  324. // then disable the Disconnect[All] buttons.
  325. //
  326. _lbVolumes.DeleteAllItems();
  327. _lbVolumes.Invalidate( TRUE );
  328. _lbUsers.DeleteAllItems();
  329. _lbUsers.Invalidate( TRUE );
  330. _pbDisconnect.Enable( FALSE );
  331. _pbDisconnectAll.Enable( FALSE );
  332. return err;
  333. }
  334. //
  335. // Get the "new" currently selected item (after the refresh).
  336. //
  337. VOLUMES_LBI * plbiNew = _lbVolumes.QueryItem();
  338. DWORD dwVolumeIdNew = (plbiNew == NULL) ? 0 : plbiNew->QueryVolumeId();
  339. if( plbiNew == NULL )
  340. {
  341. //
  342. // There is no current selection, so clear the users listbox.
  343. //
  344. err = _lbUsers.Refresh( 0 );
  345. }
  346. else
  347. if( ( plbiOld == NULL ) || ( dwVolumeIdOld != dwVolumeIdNew ) )
  348. {
  349. //
  350. // Either there was no selection before the refresh, OR
  351. // the current selection does not match the previous
  352. // selection. Therefore, fill the users listbox with
  353. // the current selection.
  354. //
  355. err = _lbUsers.Refresh( plbiNew->QueryVolumeId() );
  356. }
  357. else
  358. {
  359. //
  360. // There was no selection change after refresh. Therefore,
  361. // refresh the users listbox.
  362. //
  363. err = _lbUsers.Refresh( plbiNew->QueryVolumeId() );
  364. }
  365. if ( _lbUsers.QuerySelCount() > 0 )
  366. {
  367. _pbDisconnect.Enable( TRUE );
  368. }
  369. else
  370. {
  371. if ( _pbDisconnect.HasFocus() )
  372. {
  373. _pbOK.ClaimFocus();
  374. }
  375. _pbDisconnect.Enable( FALSE );
  376. }
  377. if ( _lbUsers.QueryCount() > 0 )
  378. {
  379. _pbDisconnectAll.Enable( TRUE );
  380. }
  381. else
  382. {
  383. if ( _pbDisconnectAll.HasFocus() )
  384. {
  385. _pbOK.ClaimFocus();
  386. }
  387. _pbDisconnectAll.Enable( FALSE );
  388. }
  389. _sltUsersCount.SetValue( _lbUsers.QueryCount() );
  390. //
  391. // Success!
  392. //
  393. return err;
  394. } // VOLUMES_DIALOG :: Refresh
  395. //
  396. // VOLUMES_LISTBOX methods.
  397. //
  398. /*******************************************************************
  399. NAME: VOLUMES_LISTBOX :: VOLUMES_LISTBOX
  400. SYNOPSIS: VOLUMEs_LISTBOX class constructor.
  401. ENTRY: powOwner - The owning window.
  402. cid - The listbox CID.
  403. hServer - The target server.
  404. EXIT: The object is constructed.
  405. HISTORY:
  406. NarenG 02-Oct-1993 Stole from Server Manager and folded
  407. BASE_RES_DIALOG and FILES_DIALOG into one.
  408. ********************************************************************/
  409. VOLUMES_LISTBOX :: VOLUMES_LISTBOX( OWNER_WINDOW * powOwner,
  410. CID cid,
  411. AFP_SERVER_HANDLE hServer )
  412. : BLT_LISTBOX( powOwner, cid ),
  413. _hServer( hServer ),
  414. _dteDisk( IDBM_LB_GOOD_VOLUME )
  415. {
  416. //
  417. // Ensure we constructed properly.
  418. //
  419. if( QueryError() != NERR_Success )
  420. {
  421. return;
  422. }
  423. APIERR err;
  424. if( ( err = _dteDisk.QueryError() ) != NERR_Success )
  425. {
  426. ReportError( err );
  427. return;
  428. }
  429. //
  430. // Build our column width table.
  431. //
  432. DISPLAY_TABLE::CalcColumnWidths( _adx,
  433. COLS_SV_LB_VOLUMES,
  434. powOwner,
  435. cid,
  436. TRUE ) ;
  437. } // VOLUMES_LISTBOX :: VOLUMES_LISTBOX
  438. /*******************************************************************
  439. NAME: VOLUMES_LISTBOX :: ~VOLUMES_LISTBOX
  440. SYNOPSIS: VOLUMES_LISTBOX class destructor.
  441. EXIT: The object is destroyed.
  442. HISTORY:
  443. NarenG 02-Oct-1993 Stole from Server Manager and folded
  444. BASE_RES_DIALOG and FILES_DIALOG into one.
  445. ********************************************************************/
  446. VOLUMES_LISTBOX :: ~VOLUMES_LISTBOX()
  447. {
  448. //
  449. // This space intentionally left blank.
  450. //
  451. } // VOLUMES_LISTBOX :: ~VOLUMES_LISTBOX
  452. /*******************************************************************
  453. NAME: VOLUMES_LISTBOX :: Refresh
  454. SYNOPSIS: Refresh the listbox, maintaining (as much as
  455. possible) the current selection state.
  456. EXIT: The listbox is feeling refreshed.
  457. RETURNS: DWORD - Any errors we encounter.
  458. HISTORY:
  459. NarenG 02-Oct-1993 Stole from Server Manager and folded
  460. BASE_RES_DIALOG and FILES_DIALOG into one.
  461. ********************************************************************/
  462. DWORD VOLUMES_LISTBOX :: Refresh( VOID )
  463. {
  464. INT iCurrent = QueryCurrentItem();
  465. INT iTop = QueryTopIndex();
  466. DWORD dwCurrentVolumeId = 0;
  467. //
  468. // Retrieve the volume id of the current selection
  469. //
  470. if ( QuerySelCount() > 0 )
  471. {
  472. dwCurrentVolumeId = QueryItem( iCurrent )->QueryVolumeId();
  473. }
  474. DWORD err = Fill();
  475. if( err != NO_ERROR )
  476. {
  477. return err;
  478. }
  479. INT cItems = QueryCount();
  480. if( cItems > 0 )
  481. {
  482. INT iSel = -1;
  483. if ( ( iCurrent >= 0 ) && ( iCurrent < cItems ) )
  484. {
  485. //
  486. // iCurrent is still valid, see if this item matches the
  487. // pre-refresh item.
  488. //
  489. if ( dwCurrentVolumeId == QueryItem( iCurrent )->QueryVolumeId() )
  490. {
  491. iSel = iCurrent;
  492. }
  493. }
  494. if ( iSel < 0 )
  495. {
  496. //
  497. // Either iCurrent was out of range or the item does not
  498. // match so search for it.
  499. //
  500. for ( INT i = 0; i < cItems; i++ )
  501. {
  502. VOLUMES_LBI * plbi = QueryItem( i );
  503. if ( dwCurrentVolumeId == plbi->QueryVolumeId() )
  504. {
  505. iSel = i;
  506. break;
  507. }
  508. }
  509. }
  510. if ( iSel < 0 )
  511. {
  512. //
  513. // If no selection found then default = first item
  514. //
  515. iSel = 0;
  516. }
  517. //
  518. // If the previous top index is out of range then
  519. // set default = first item.
  520. //
  521. if ( ( iTop < 0 ) || ( iTop >= cItems ) )
  522. {
  523. iTop = 0;
  524. }
  525. SetTopIndex( iTop );
  526. SelectItem( iSel );
  527. }
  528. return NO_ERROR;
  529. } // VOLUMES_LISTBOX :: Refresh
  530. /*******************************************************************
  531. NAME: VOLUMES_LISTBOX :: Fill
  532. SYNOPSIS: Fills the listbox with the available sharepoints.
  533. EXIT: The listbox is filled.
  534. RETURNS: DWORD - Any errors encountered.
  535. HISTORY:
  536. NarenG 02-Oct-1993 Stole from Server Manager and folded
  537. BASE_RES_DIALOG and FILES_DIALOG into one.
  538. ********************************************************************/
  539. DWORD VOLUMES_LISTBOX :: Fill( VOID )
  540. {
  541. //
  542. // Just to be cool...
  543. //
  544. AUTO_CURSOR Cursor;
  545. //
  546. // Enumerate all successfully shared volumes.
  547. //
  548. PAFP_VOLUME_INFO pAfpVolumes;
  549. DWORD cEntriesRead;
  550. DWORD cTotalAvail;
  551. DWORD err = ::AfpAdminVolumeEnum( _hServer,
  552. (LPBYTE*)&pAfpVolumes,
  553. (DWORD)-1, // Get all volumes
  554. &cEntriesRead,
  555. &cTotalAvail,
  556. NULL );
  557. //
  558. // See if the volumes are available.
  559. //
  560. if( err != NO_ERROR )
  561. {
  562. return err;
  563. }
  564. //
  565. // Now that we know the volume info is available,
  566. // let's nuke everything in the listbox.
  567. //
  568. SetRedraw( FALSE );
  569. DeleteAllItems();
  570. //
  571. // For iterating the available sharepoints.
  572. //
  573. PAFP_VOLUME_INFO pVolIter = pAfpVolumes;
  574. //
  575. // Iterate the volumes adding them to the listbox.
  576. //
  577. err = NO_ERROR;
  578. while( ( err == NO_ERROR ) && ( cEntriesRead-- ) )
  579. {
  580. VOLUMES_LBI * pslbi = new VOLUMES_LBI( pVolIter->afpvol_id,
  581. pVolIter->afpvol_name,
  582. pVolIter->afpvol_path,
  583. pVolIter->afpvol_curr_uses,
  584. &_dteDisk );
  585. if( AddItem( pslbi ) < 0 )
  586. {
  587. //
  588. // CODEWORK: What should we do in error conditions?
  589. // As currently spec'd, we do nothing. If the data
  590. // cannot be retrieved, we display "n/a" in the
  591. // statistics strings. Should we hide the listbox
  592. // and display a message a'la WINNET??
  593. //
  594. err = ERROR_NOT_ENOUGH_MEMORY;
  595. }
  596. pVolIter++;
  597. }
  598. ::AfpAdminBufferFree( pAfpVolumes );
  599. SetRedraw( TRUE );
  600. Invalidate( TRUE );
  601. return err;
  602. } // VOLUMES_LISTBOX :: Fill
  603. //
  604. // VOLUMES_LBI methods.
  605. //
  606. /*******************************************************************
  607. NAME: VOLUMES_LBI :: VOLUMES_LBI
  608. SYNOPSIS: VOLUMES_LBI class constructor.
  609. ENTRY: pszVolumeName - The sharepoint name.
  610. pszPath - The path for this sharepoint.
  611. cUses - Number of uses for this share.
  612. EXIT: The object is constructed.
  613. HISTORY:
  614. NarenG 02-Oct-1993 Stole from Server Manager and folded
  615. BASE_RES_DIALOG and FILES_DIALOG into one.
  616. ********************************************************************/
  617. VOLUMES_LBI :: VOLUMES_LBI( DWORD dwVolumeId,
  618. const TCHAR * pszVolumeName,
  619. const TCHAR * pszPath,
  620. DWORD cUses,
  621. DMID_DTE * pdte )
  622. : _dwVolumeId( dwVolumeId ),
  623. _nlsVolumeName( pszVolumeName ),
  624. _pdte( pdte ),
  625. _nlsPath( pszPath ),
  626. _nlsUses( cUses )
  627. {
  628. UIASSERT( pszVolumeName != NULL );
  629. UIASSERT( pdte != NULL );
  630. //
  631. // Ensure we constructed properly.
  632. //
  633. if( QueryError() != NERR_Success )
  634. {
  635. return;
  636. }
  637. APIERR err;
  638. if( ( ( err = _nlsPath.QueryError() ) != NERR_Success ) ||
  639. ( ( err = _nlsUses.QueryError() ) != NERR_Success ) ||
  640. ( ( err = _nlsVolumeName.QueryError() ) != NERR_Success ) )
  641. {
  642. ReportError( err );
  643. return;
  644. }
  645. } // VOLUMES_LBI :: VOLUMES_LBI
  646. /*******************************************************************
  647. NAME: VOLUMES_LBI :: ~VOLUMES_LBI
  648. SYNOPSIS: VOLUMES_LBI class destructor.
  649. EXIT: The object is destroyed.
  650. HISTORY:
  651. NarenG 02-Oct-1993 Stole from Server Manager and folded
  652. BASE_RES_DIALOG and FILES_DIALOG into one.
  653. ********************************************************************/
  654. VOLUMES_LBI :: ~VOLUMES_LBI()
  655. {
  656. _pdte = NULL;
  657. } // VOLUMES_LBI :: ~VOLUMES_LBI
  658. /*******************************************************************
  659. NAME: VOLUMES_LBI :: Paint
  660. SYNOPSIS: Draw an entry in VOLUMES_LISTBOX.
  661. ENTRY: plb - Pointer to a BLT_LISTBOX.
  662. hdc - The DC to draw upon.
  663. prect - Clipping rectangle.
  664. pGUILTT - GUILTT info.
  665. EXIT: The item is drawn.
  666. HISTORY:
  667. NarenG 02-Oct-1993 Stole from Server Manager and folded
  668. BASE_RES_DIALOG and FILES_DIALOG into one.
  669. ********************************************************************/
  670. VOID VOLUMES_LBI :: Paint( LISTBOX * plb,
  671. HDC hdc,
  672. const RECT * prect,
  673. GUILTT_INFO * pGUILTT ) const
  674. {
  675. STR_DTE_ELLIPSIS dteVolumeName( _nlsVolumeName.QueryPch(),
  676. plb, ELLIPSIS_RIGHT );
  677. STR_DTE dteUses( _nlsUses.QueryPch() );
  678. STR_DTE_ELLIPSIS dtePath( _nlsPath.QueryPch(), plb, ELLIPSIS_PATH );
  679. DISPLAY_TABLE dtab( COLS_SV_LB_VOLUMES,
  680. ((VOLUMES_LISTBOX *)plb)->QueryColumnWidths() );
  681. dtab[0] = _pdte;
  682. dtab[1] = &dteVolumeName;
  683. dtab[2] = &dteUses;
  684. dtab[3] = &dtePath;
  685. dtab.Paint( plb, hdc, prect, pGUILTT );
  686. } // VOLUMES_LBI :: Paint
  687. /*******************************************************************
  688. NAME: VOLUMES_LBI :: NotifyNewUseCount
  689. SYNOPSIS: Notifies the LBI that the "use" count has changed.
  690. ENTRY: cUses - The new use count.
  691. RETURNS: DWORD - Any errors that occur.
  692. HISTORY:
  693. NarenG 02-Oct-1993 Stole from Server Manager and folded
  694. BASE_RES_DIALOG and FILES_DIALOG into one.
  695. ********************************************************************/
  696. APIERR VOLUMES_LBI :: NotifyNewUseCount( DWORD cUses )
  697. {
  698. DEC_STR nls( cUses );
  699. APIERR err = nls.QueryError();
  700. if( err == NERR_Success )
  701. {
  702. err = _nlsUses.CopyFrom( nls );
  703. }
  704. return err;
  705. } // VOLUMES_LBI :: NotifyNewUseCount
  706. /*******************************************************************
  707. NAME: VOLUMES_LBI :: QueryLeadingChar
  708. SYNOPSIS: Returns the first character in the resource name.
  709. This is used for the listbox keyboard interface.
  710. RETURNS: WCHAR - The first character in the
  711. resource name.
  712. HISTORY:
  713. NarenG 02-Oct-1993 Stole from Server Manager and folded
  714. BASE_RES_DIALOG and FILES_DIALOG into one.
  715. ********************************************************************/
  716. WCHAR VOLUMES_LBI :: QueryLeadingChar( VOID ) const
  717. {
  718. ISTR istr( _nlsVolumeName );
  719. return _nlsVolumeName.QueryChar( istr );
  720. } // VOLUMES_LBI :: QueryLeadingChar
  721. /*******************************************************************
  722. NAME: VOLUMES_LBI :: Compare
  723. SYNOPSIS: Compare two BASE_RES_LBI items.
  724. ENTRY: plbi - The LBI to compare against.
  725. RETURNS: INT - The result of the compare
  726. ( <0 , ==0 , >0 ).
  727. HISTORY:
  728. NarenG 02-Oct-1993 Stole from Server Manager and folded
  729. BASE_RES_DIALOG and FILES_DIALOG into one.
  730. ********************************************************************/
  731. INT VOLUMES_LBI :: Compare( const LBI * plbi ) const
  732. {
  733. return _nlsVolumeName._stricmp( ((const VOLUMES_LBI *)plbi)->_nlsVolumeName);
  734. } // VOLUMES_LBI :: Compare
  735. //
  736. // USERS_LISTBOX methods.
  737. //
  738. /*******************************************************************
  739. NAME: USERS_LISTBOX :: USERS_LISTBOX
  740. SYNOPSIS: USERS_LISTBOX class constructor.
  741. ENTRY: powner - The owning window.
  742. cid - The listbox CID.
  743. hServer - Handlr to the remote server.
  744. EXIT: The object is constructed.
  745. HISTORY:
  746. NarenG 02-Oct-1993 Stole from Server Manager and folded
  747. BASE_RES_DIALOG and FILES_DIALOG into one.
  748. ********************************************************************/
  749. USERS_LISTBOX :: USERS_LISTBOX( OWNER_WINDOW * powner,
  750. CID cid,
  751. AFP_SERVER_HANDLE hServer )
  752. : BLT_LISTBOX( powner, cid ),
  753. _hServer( hServer ),
  754. _dteIcon( IDBM_LB_USER )
  755. {
  756. //
  757. // Make sure everything constructed properly.
  758. //
  759. if( QueryError() != NERR_Success )
  760. {
  761. return;
  762. }
  763. APIERR err;
  764. if( ( err = _dteIcon.QueryError() ) != NERR_Success )
  765. {
  766. ReportError( err );
  767. return;
  768. }
  769. //
  770. // Retrieve the time separator.
  771. //
  772. NLS_STR nlsTimeSep;
  773. if( ( err = nlsTimeSep.QueryError() ) != NERR_Success )
  774. {
  775. ReportError( err );
  776. return;
  777. }
  778. INTL_PROFILE intl;
  779. if( ( err = intl.QueryError() ) != NERR_Success )
  780. {
  781. ReportError( intl.QueryError() );
  782. return;
  783. }
  784. if ( ( err = intl.QueryTimeSeparator( &nlsTimeSep ) ) != NERR_Success )
  785. {
  786. ReportError( err );
  787. return;
  788. }
  789. UIASSERT( nlsTimeSep.QueryTextLength() == 1 );
  790. _chTimeSep = *(nlsTimeSep.QueryPch());
  791. //
  792. // Build the column width table used for
  793. // displaying the listbox items.
  794. //
  795. DISPLAY_TABLE::CalcColumnWidths( _adx,
  796. COLS_SV_LB_USERS,
  797. powner,
  798. cid,
  799. TRUE) ;
  800. } // USERS_LISTBOX :: USERS_LISTBOX
  801. /*******************************************************************
  802. NAME: USERS_LISTBOX :: ~USERS_LISTBOX
  803. SYNOPSIS: USERS_LISTBOX class destructor.
  804. EXIT: The object is destroyed.
  805. HISTORY:
  806. NarenG 02-Oct-1993 Stole from Server Manager and folded
  807. BASE_RES_DIALOG and FILES_DIALOG into one.
  808. ********************************************************************/
  809. USERS_LISTBOX :: ~USERS_LISTBOX()
  810. {
  811. //
  812. // This space intentionally left blank.
  813. //
  814. } // USERS_LISTBOX :: ~USERS_LISTBOX
  815. /*******************************************************************
  816. NAME: USERS_LISTBOX :: Fill
  817. SYNOPSIS: Fills the listbox with the connected users.
  818. ENTRY: pszShare - The target sharename. Note
  819. that this sharename is "sticky"
  820. in that it will be used in
  821. subsequent Refresh() calls.
  822. EXIT: The listbox is filled.
  823. RETURNS: APIERR - Any errors encountered.
  824. HISTORY:
  825. NarenG 02-Oct-1993 Stole from Server Manager and folded
  826. BASE_RES_DIALOG and FILES_DIALOG into one.
  827. ********************************************************************/
  828. DWORD USERS_LISTBOX :: Fill( DWORD dwVolumeId )
  829. {
  830. //
  831. // Just to be cool...
  832. //
  833. AUTO_CURSOR Cursor;
  834. //
  835. // Nuke the listbox.
  836. //
  837. DeleteAllItems();
  838. //
  839. // If the Volume Id is zero (a valid scenario) then
  840. // there are no connections in the listbox.
  841. //
  842. if( dwVolumeId == 0 )
  843. {
  844. return NO_ERROR;
  845. }
  846. //
  847. // Enumerate the connections to this volume.
  848. //
  849. PAFP_CONNECTION_INFO pAfpConnections;
  850. DWORD cEntriesRead;
  851. DWORD cTotalAvail;
  852. DWORD err = ::AfpAdminConnectionEnum( _hServer,
  853. (LPBYTE*)&pAfpConnections,
  854. AFP_FILTER_ON_VOLUME_ID,
  855. dwVolumeId,
  856. (DWORD)-1, // Get all conenctions
  857. &cEntriesRead,
  858. &cTotalAvail,
  859. NULL );
  860. //
  861. // See if the connections are available.
  862. //
  863. if( err != NO_ERROR )
  864. {
  865. return err;
  866. }
  867. SetRedraw( FALSE );
  868. //
  869. // For iterating the available connections.
  870. //
  871. PAFP_CONNECTION_INFO pConnIter = pAfpConnections;
  872. //
  873. // Iterate the connections adding them to the listbox.
  874. //
  875. while( ( err == NO_ERROR ) && ( cEntriesRead-- ) )
  876. {
  877. USERS_LBI * pclbi = new USERS_LBI( pConnIter->afpconn_id,
  878. pConnIter->afpconn_username,
  879. pConnIter->afpconn_time,
  880. pConnIter->afpconn_num_opens,
  881. _chTimeSep,
  882. &_dteIcon );
  883. if( AddItem( pclbi ) < 0 )
  884. {
  885. err = ERROR_NOT_ENOUGH_MEMORY;
  886. }
  887. pConnIter++;
  888. }
  889. ::AfpAdminBufferFree( pAfpConnections );
  890. SetRedraw( TRUE );
  891. Invalidate( TRUE );
  892. return err;
  893. } // USERS_LISTBOX :: Fill
  894. /*******************************************************************
  895. NAME: USERS_LISTBOX :: Refresh
  896. SYNOPSIS: Refreshes the listbox, maintaining (as much as
  897. possible) the relative position of the current
  898. selection.
  899. EXIT: The listbox is feeling refreshed.
  900. RETURNS: DWORD - Any errors encountered.
  901. HISTORY:
  902. NarenG 02-Oct-1993 Stole from Server Manager and folded
  903. BASE_RES_DIALOG and FILES_DIALOG into one.
  904. ********************************************************************/
  905. DWORD USERS_LISTBOX :: Refresh( DWORD dwVolumeId )
  906. {
  907. INT iCurrent = QueryCurrentItem();
  908. INT iTop = QueryTopIndex();
  909. DWORD err = Fill( dwVolumeId );
  910. if( err != NO_ERROR )
  911. {
  912. return err;
  913. }
  914. INT cItems = QueryCount();
  915. if( cItems > 0 )
  916. {
  917. iCurrent = min( max( iCurrent, 0 ), cItems - 1 );
  918. iTop = min( max( iTop, 0 ), cItems - 1 );
  919. SelectItem( iCurrent );
  920. SetTopIndex( iTop );
  921. }
  922. return NO_ERROR;
  923. } // USERS_LISTBOX :: Refresh
  924. /*******************************************************************
  925. NAME: USERS_LISTBOX :: AreResourcesOpen
  926. SYNOPSIS: Returns TRUE if any user in the listbox has any
  927. resources open.
  928. RETURNS: BOOL
  929. HISTORY:
  930. NarenG 02-Oct-1993 Stole from Server Manager and folded
  931. BASE_RES_DIALOG and FILES_DIALOG into one.
  932. ********************************************************************/
  933. BOOL USERS_LISTBOX :: AreResourcesOpen( VOID ) const
  934. {
  935. INT cItems = QueryCount();
  936. for( INT i = 0 ; i < cItems ; i++ )
  937. {
  938. USERS_LBI * plbi = QueryItem( i );
  939. if( plbi->QueryNumOpens() > 0 )
  940. {
  941. return TRUE;
  942. }
  943. }
  944. return FALSE;
  945. } // USERS_LISTBOX :: AreResourcesOpen
  946. //
  947. // USERS_LBI methods.
  948. //
  949. /*******************************************************************
  950. NAME: USERS_LBI :: USERS_LBI
  951. SYNOPSIS: USERS_LBI class constructor.
  952. ENTRY: pszUserName - The user for this entry.
  953. pszComputerName - The user's computer name.
  954. ulTime - Connection time.
  955. cOpens - Number of opens on this connection.
  956. chTimeSep - Time format separator.
  957. EXIT: The object is constructed.
  958. HISTORY:
  959. NarenG 02-Oct-1993 Stole from Server Manager and folded
  960. BASE_RES_DIALOG and FILES_DIALOG into one.
  961. ********************************************************************/
  962. USERS_LBI :: USERS_LBI( DWORD dwConnectionId,
  963. const TCHAR * pszUserName,
  964. ULONG ulTime,
  965. DWORD cOpens,
  966. TCHAR chTimeSep,
  967. DMID_DTE * pdte )
  968. : _dwConnectionId( dwConnectionId ),
  969. _nlsInUse(),
  970. _nlsUserName(),
  971. _nlsTime( ulTime, chTimeSep ),
  972. _pdte( pdte ),
  973. _cOpens( cOpens )
  974. {
  975. //
  976. // Make sure everything constructed properly.
  977. //
  978. if( QueryError() != NERR_Success )
  979. {
  980. return;
  981. }
  982. APIERR err;
  983. if( ( ( err = _nlsUserName.QueryError() ) != NERR_Success ) ||
  984. ( ( err = _nlsInUse.QueryError() ) != NERR_Success ) ||
  985. ( ( err = _nlsTime.QueryError() ) != NERR_Success ) )
  986. {
  987. ReportError( err );
  988. return;
  989. }
  990. //
  991. // Build the more complex display strings.
  992. //
  993. err = _nlsInUse.Load( ( cOpens > 0 ) ? IDS_YES : IDS_NO );
  994. if ( err == NERR_Success )
  995. {
  996. if ( pszUserName == NULL )
  997. {
  998. err = _nlsUserName.Load( IDS_GUEST );
  999. }
  1000. else
  1001. {
  1002. err = _nlsUserName.CopyFrom( pszUserName );
  1003. }
  1004. }
  1005. if( err != NERR_Success )
  1006. {
  1007. ReportError( err );
  1008. return;
  1009. }
  1010. } // USERS_LBI :: USERS_LBI
  1011. /*******************************************************************
  1012. NAME: USERS_LBI :: ~USERS_LBI
  1013. SYNOPSIS: USERS_LBI class destructor.
  1014. EXIT: The object is destroyed.
  1015. HISTORY:
  1016. NarenG 02-Oct-1993 Stole from Server Manager and folded
  1017. BASE_RES_DIALOG and FILES_DIALOG into one.
  1018. ********************************************************************/
  1019. USERS_LBI :: ~USERS_LBI()
  1020. {
  1021. //
  1022. // This space intentionally left blank.
  1023. //
  1024. } // USERS_LBI :: ~USERS_LBI
  1025. /*******************************************************************
  1026. NAME: USERS_LBI :: Paint
  1027. SYNOPSIS: Draw an entry in USERS_LISTBOX.
  1028. ENTRY: plb - Pointer to a BLT_LISTBOX.
  1029. hdc - The DC to draw upon.
  1030. prect - Clipping rectangle.
  1031. pGUILTT - GUILTT info.
  1032. EXIT: The item is drawn.
  1033. HISTORY:
  1034. NarenG 02-Oct-1993 Stole from Server Manager and folded
  1035. BASE_RES_DIALOG and FILES_DIALOG into one.
  1036. ********************************************************************/
  1037. VOID USERS_LBI :: Paint( LISTBOX * plb,
  1038. HDC hdc,
  1039. const RECT * prect,
  1040. GUILTT_INFO * pGUILTT ) const
  1041. {
  1042. STR_DTE_ELLIPSIS dteUserName( _nlsUserName.QueryPch(),
  1043. plb, ELLIPSIS_RIGHT );
  1044. STR_DTE dteTime( _nlsTime.QueryPch() );
  1045. STR_DTE dteInUse( _nlsInUse.QueryPch() );
  1046. DISPLAY_TABLE dtab( COLS_SV_LB_USERS,
  1047. ((USERS_LISTBOX *)plb)->QueryColumnWidths() );
  1048. dtab[0] = _pdte;
  1049. dtab[1] = &dteUserName;
  1050. dtab[2] = &dteTime;
  1051. dtab[3] = &dteInUse;
  1052. dtab.Paint( plb, hdc, prect, pGUILTT );
  1053. } // USERS_LBI :: Paint
  1054. /*******************************************************************
  1055. NAME: USERS_LBI :: QueryLeadingChar
  1056. SYNOPSIS: Return the leading character of this item.
  1057. RETURNS: WCHAR - The leading character.
  1058. HISTORY:
  1059. NarenG 02-Oct-1993 Stole from Server Manager and folded
  1060. BASE_RES_DIALOG and FILES_DIALOG into one.
  1061. ********************************************************************/
  1062. WCHAR USERS_LBI :: QueryLeadingChar( VOID ) const
  1063. {
  1064. ISTR istr( _nlsUserName );
  1065. return _nlsUserName.QueryChar( istr );
  1066. } // USERS_LBI :: QueryLeadingChar
  1067. /*******************************************************************
  1068. NAME: USERS_LBI :: Compare
  1069. SYNOPSIS: Compare two USERS_LBI items.
  1070. ENTRY: plbi - The "other" item.
  1071. RETURNS: INT - 0 if the items match.
  1072. -1 if we're < the other item.
  1073. +1 if we're > the other item.
  1074. HISTORY:
  1075. NarenG 02-Oct-1993 Stole from Server Manager and folded
  1076. BASE_RES_DIALOG and FILES_DIALOG into one.
  1077. ********************************************************************/
  1078. INT USERS_LBI :: Compare( const LBI * plbi ) const
  1079. {
  1080. NLS_STR * pnls = &(((USERS_LBI *)plbi)->_nlsUserName);
  1081. return _nlsUserName._stricmp( *pnls );
  1082. } // USERS_LBI :: Compare