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.

1599 lines
35 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1991 **/
  4. /**********************************************************************/
  5. /*
  6. dialogs.cxx
  7. This module contains the Add Port and Configure dialogs.
  8. FILE HISTORY:
  9. NarenG 17-May-1993 Converted C code for the 2 dialogs to C++
  10. */
  11. #define INCL_NET
  12. #define INCL_NETLIB
  13. #define INCL_NETSERVICE
  14. #define INCL_WINDOWS
  15. #define INCL_WINDOWS_GDI
  16. #define INCL_NETERRORS
  17. #define INCL_DOSERRORS
  18. #include <lmui.hxx>
  19. #if defined(DEBUG)
  20. static const CHAR szFileName[] = __FILE__;
  21. #define _FILENAME_DEFINED_ONCE szFileName
  22. #endif
  23. #include <uiassert.hxx>
  24. #include <uitrace.hxx>
  25. #define INCL_BLT_WINDOW
  26. #define INCL_BLT_DIALOG
  27. #define INCL_BLT_CONTROL
  28. #define INCL_BLT_CLIENT
  29. #define INCL_BLT_MSGPOPUP
  30. #define INCL_BLT_EVENT
  31. #define INCL_BLT_MISC
  32. #define INCL_BLT_TIMER
  33. #define INCL_BLT_CC
  34. #include <blt.hxx>
  35. #include <dbgstr.hxx>
  36. extern "C"
  37. {
  38. #include <stdlib.h>
  39. #include <winsock.h>
  40. #include <atalkwsh.h>
  41. #include "atalkmon.h"
  42. #include "dialogs.h"
  43. } // extern "C"
  44. //#include <colwidth.hxx>
  45. #include <ellipsis.hxx>
  46. #include "getprint.hxx"
  47. #include "dialogs.hxx"
  48. #define STRING_SIZE_CHARS 255
  49. #define STRING_SIZE_BYTES (STRING_SIZE_CHARS * sizeof(WCHAR))
  50. /*******************************************************************
  51. NAME: InitializeBlt
  52. SYNOPSIS: Called during processing of DLL_PROCESS_ATTACH notification to
  53. initialize the DLL.
  54. ENTRY:
  55. RETURNS: BOOL - TRUE = AfpMgr should be installed.
  56. FALSE = AfpMgr cannot be installed.
  57. HISTORY:
  58. NarenG 71-May-1993 Created
  59. ********************************************************************/
  60. BOOL InitializeBlt( VOID )
  61. {
  62. WaitForSingleObject( hmutexBlt, INFINITE );
  63. //
  64. // Initialize all of the NetUI goodies.
  65. //
  66. APIERR err = BLT::Init( (HINSTANCE)hInst,
  67. IDRSRC_RASMAC_BASE, IDRSRC_RASMAC_LAST,
  68. IDS_UI_RASMAC_BASE, IDS_UI_RASMAC_LAST );
  69. if( err == NERR_Success )
  70. {
  71. err = BLT_MASTER_TIMER::Init();
  72. if( err != NERR_Success )
  73. {
  74. //
  75. // BLT initialized OK, but BLT_MASTER_TIMER
  76. // failed. So, before we bag-out, we must
  77. // deinitialize BLT.
  78. //
  79. BLT::Term( (HINSTANCE)hInst );
  80. }
  81. }
  82. if( err == NERR_Success )
  83. {
  84. err = BLT::RegisterHelpFile( (HINSTANCE)hInst,
  85. IDS_MACPRINT_HELPFILENAME,
  86. HC_UI_RASMAC_BASE,
  87. HC_UI_RASMAC_LAST );
  88. if( err != NERR_Success )
  89. {
  90. //
  91. // This is the only place where we can safely
  92. // invoke MsgPopup, since we *know* that all of
  93. // the BLT goodies were initialized properly.
  94. //
  95. // ::MsgPopup( QueryHwnd(), err );
  96. }
  97. }
  98. if ( err != NERR_Success )
  99. ReleaseMutex( hmutexBlt );
  100. return err == NERR_Success;
  101. } // InitializeBlt
  102. /*******************************************************************
  103. NAME: TerminateBlt
  104. SYNOPSIS: Called during processing of DLL_PROCESS_DETACH notification to
  105. terminate the DLL.
  106. ENTRY:
  107. HISTORY:
  108. NarenG 24-May-1993 Created.
  109. ********************************************************************/
  110. VOID TerminateBlt( VOID )
  111. {
  112. //
  113. // Kill the NetUI goodies.
  114. //
  115. BLT_MASTER_TIMER::Term();
  116. BLT::Term( (HINSTANCE)hInst );
  117. ReleaseMutex( hmutexBlt );
  118. } // TerminateBlt
  119. /********************************************************************
  120. NAME: ConfigPortDialog
  121. SYNOPSIS: Called to bring up the configure port dialog.
  122. ENTRY: lParam is a pointer to an ATALKPORT structure for the
  123. port being configured.
  124. HISTORY:
  125. NarenG 24-May-1993 Created.
  126. *********************************************************************/
  127. BOOL ConfigPortDialog( HWND hdlg, BOOL fIsSpooler, BOOL * pfCapture )
  128. {
  129. if ( !InitializeBlt() )
  130. {
  131. return FALSE;
  132. }
  133. //
  134. // If this is a spooler then we have nothing to configure
  135. //
  136. if ( fIsSpooler )
  137. {
  138. ::MsgPopup( hdlg, IDS_NOTHING_TO_CONFIGURE, MPSEV_INFO, 1, MP_OK );
  139. TerminateBlt();
  140. return FALSE;
  141. }
  142. BOOL fOk = FALSE;
  143. CONFIGURE_PORT_DIALOG * pdlg = new CONFIGURE_PORT_DIALOG( hdlg, pfCapture );
  144. APIERR err = ( pdlg == NULL ) ? ERROR_NOT_ENOUGH_MEMORY
  145. : pdlg->Process( &fOk );
  146. delete pdlg;
  147. if ( err != NO_ERROR )
  148. {
  149. ::MsgPopup( hdlg, err );
  150. TerminateBlt() ;
  151. return FALSE;
  152. }
  153. TerminateBlt();
  154. return fOk;
  155. }
  156. /********************************************************************
  157. NAME: CONFIGURE_PORT_DIALOG::CONFIGURE_PORT_DIALOG
  158. SYNOPSIS: CONFIGURE_PORT_DIALOG constructor
  159. ENTRY: hwndOwner - Handle to the owner window.
  160. pAtalkPort - Pointer to the ATALKPORT structure for the
  161. port being configured.
  162. HISTORY:
  163. NarenG 24-May-1993 Created.
  164. *********************************************************************/
  165. CONFIGURE_PORT_DIALOG::CONFIGURE_PORT_DIALOG( HWND hWndOwner,
  166. BOOL * pfCapture )
  167. : DIALOG_WINDOW( MAKEINTRESOURCE(IDD_CONFIG_PORT_DIALOG ), hWndOwner ),
  168. _pfCapture( pfCapture ),
  169. _chkCapture( this, IDCP_CHK_CAPTURE )
  170. {
  171. //
  172. // Make sure everything constructed correctly
  173. //
  174. if ( QueryError() != NERR_Success )
  175. {
  176. return;
  177. }
  178. APIERR err;
  179. if ( (( err = _chkCapture.QueryError() ) != NERR_Success ) )
  180. {
  181. ReportError( err );
  182. return;
  183. }
  184. _chkCapture.SetCheck( *pfCapture );
  185. }
  186. /********************************************************************
  187. NAME: CONFIGURE_PORT_DIALOG::OnOK
  188. SYNOPSIS: Called when the user hits the OK button
  189. ENTRY:
  190. HISTORY:
  191. NarenG 24-May-1993 Created.
  192. *********************************************************************/
  193. BOOL CONFIGURE_PORT_DIALOG::OnOK( VOID )
  194. {
  195. *_pfCapture = _chkCapture.QueryCheck();
  196. Dismiss( TRUE );
  197. return TRUE;
  198. }
  199. /*******************************************************************
  200. NAME: CONFIGURE_PORT_DIALOG :: QueryHelpContext
  201. SYNOPSIS: This function returns the appropriate help context
  202. value (HC_*) for this particular dialog.
  203. RETURNS: ULONG - The help context for this
  204. dialog.
  205. ********************************************************************/
  206. ULONG CONFIGURE_PORT_DIALOG :: QueryHelpContext( void )
  207. {
  208. return HC_CONFIGURE_PORT_DIALOG;
  209. } // CONFIGURE_PORT_DIALOG :: QueryHelpContext
  210. /*********************************************************************
  211. NAME: AddPortDialog
  212. SYNOPSIS: Called to bring dialog to add a port.
  213. ENTRY: lParam - Pointer to the ATALKPORT structure for the
  214. new port being added.
  215. HISTORY:
  216. NarenG 24-May-1993 Created.
  217. ***********************************************************************/
  218. BOOL AddPortDialog( HWND hdlg, PATALKPORT pAtalkPort )
  219. {
  220. if ( !InitializeBlt() )
  221. return FALSE;
  222. BOOL fOk = FALSE;
  223. ADD_PORT_DIALOG * pdlg = new ADD_PORT_DIALOG( hdlg, pAtalkPort );
  224. APIERR err = ( pdlg == NULL ) ? ERROR_NOT_ENOUGH_MEMORY
  225. : pdlg->Process( &fOk );
  226. delete pdlg;
  227. if ( err != NO_ERROR )
  228. {
  229. ::MsgPopup( hdlg, err );
  230. TerminateBlt() ;
  231. return FALSE;
  232. }
  233. TerminateBlt();
  234. return fOk;
  235. }
  236. /********************************************************************
  237. NAME: ADD_PORT_DIALOG::ADD_PORT_DIALOG
  238. SYNOPSIS: ADD_PORT_DIALOG constructor
  239. ENTRY: hwndOwner - Handle to the owner window.
  240. pNewPort - Pointer to the ATALKPORT structure for the
  241. new port being added.
  242. HISTORY:
  243. NarenG 24-May-1993 Created.
  244. *********************************************************************/
  245. ADD_PORT_DIALOG::ADD_PORT_DIALOG( HWND hWndOwner,
  246. PATALKPORT pNewPort )
  247. : DIALOG_WINDOW( MAKEINTRESOURCE(IDD_ADDPORT_DIALOG), hWndOwner ),
  248. _pNewPort( pNewPort ),
  249. _pbOK( this, IDOK ),
  250. _ollb( this, IDAP_LB_OUTLINE, pNewPort->sockQuery )
  251. {
  252. //
  253. // Make sure everything constructed correctly
  254. //
  255. if ( QueryError() != NERR_Success )
  256. {
  257. return;
  258. }
  259. APIERR err;
  260. if ( pNewPort->sockQuery == INVALID_SOCKET )
  261. {
  262. ReportError( IDS_MUST_START_STACK );
  263. return;
  264. }
  265. if ( (( err = _ollb.QueryError() ) != NERR_Success ) ||
  266. (( err = _pbOK.QueryError() ) != NERR_Success ) )
  267. {
  268. ReportError( err );
  269. return;
  270. }
  271. //
  272. // Just to be cool...
  273. //
  274. AUTO_CURSOR Cursor;
  275. //
  276. // Initialize the outline listbox with Zones
  277. //
  278. err = _ollb.FillZones();
  279. if ( err != NO_ERROR )
  280. {
  281. ReportError( err );
  282. return;
  283. }
  284. if ( _ollb.QueryCount() > 0 )
  285. {
  286. OLLB_ENTRY * pollbe = _ollb.QueryItem( 0 );
  287. if ( ( _ollb.QueryCount() == 1 ) &&
  288. ( ::_wcsicmp( pollbe->QueryZone(), (LPWSTR)TEXT("*") ) == 0 ) )
  289. {
  290. Show();
  291. err = _ollb.ExpandZone( 0 );
  292. if ( err != NO_ERROR )
  293. {
  294. ReportError( err );
  295. return;
  296. }
  297. }
  298. _ollb.SelectItem( 0 );
  299. }
  300. else
  301. {
  302. ReportError( IDS_NO_ZONES );
  303. return;
  304. }
  305. return;
  306. }
  307. /*******************************************************************
  308. NAME: ADD_PORT_DIALOG :: ~ADD_PORT_DIALOG
  309. SYNOPSIS: ADD_PORT_DIALOG class destructor.
  310. EXIT: The object is destroyed.
  311. HISTORY:
  312. NarenG 25-May-1993 Created
  313. ********************************************************************/
  314. ADD_PORT_DIALOG :: ~ADD_PORT_DIALOG()
  315. {
  316. //
  317. // Nothing to be done here.
  318. //
  319. } // ADD_PORT_DIALOG :: ~ADD_PORT_DIALOG
  320. /*******************************************************************
  321. NAME: ADD_PORT_DIALOG :: QueryHelpContext
  322. SYNOPSIS: This function returns the appropriate help context
  323. value (HC_*) for this particular dialog.
  324. RETURNS: ULONG - The help context for this
  325. dialog.
  326. ********************************************************************/
  327. ULONG ADD_PORT_DIALOG :: QueryHelpContext( void )
  328. {
  329. return HC_ADD_PORT_DIALOG;
  330. } // ADD_PORT_DIALOG :: QueryHelpContext
  331. /********************************************************************
  332. NAME: ADD_PORT_DIALOG::OnCommand
  333. SYNOPSIS: Called whenever a WM_COMMAND message is send to the
  334. dialog procedure.
  335. ENTRY:
  336. HISTORY:
  337. NarenG 24-May-1993 Created.
  338. *********************************************************************/
  339. BOOL ADD_PORT_DIALOG::OnCommand( const CONTROL_EVENT & event )
  340. {
  341. if ( event.QueryCid() == _ollb.QueryCid() )
  342. {
  343. //
  344. // This method handles double clicks of domains
  345. //
  346. if ( event.QueryCode() == LBN_DBLCLK )
  347. {
  348. INT i = _ollb.QueryCurrentItem();
  349. OLLB_ENTRY * pollbe = _ollb.QueryItem( i );
  350. if ( pollbe == NULL )
  351. {
  352. return FALSE;
  353. }
  354. if ( pollbe->QueryType() == SFM_OLLBL_ZONE )
  355. {
  356. //
  357. // Toggle zone.
  358. //
  359. if ( pollbe->IsExpanded() )
  360. return _ollb.CollapseZone( i );
  361. else
  362. return _ollb.ExpandZone( i );
  363. }
  364. else
  365. {
  366. return OnOK();
  367. }
  368. }
  369. }
  370. return DIALOG_WINDOW::OnCommand( event );
  371. }
  372. /********************************************************************
  373. NAME: ADD_PORT_DIALOG::OnOK
  374. SYNOPSIS: Called when the user hits the OK button
  375. ENTRY:
  376. HISTORY:
  377. NarenG 24-May-1993 Created.
  378. *********************************************************************/
  379. BOOL ADD_PORT_DIALOG::OnOK( VOID )
  380. {
  381. //
  382. // Just to be cool...
  383. //
  384. AUTO_CURSOR Cursor;
  385. OLLB_ENTRY * pollbe = _ollb.QueryItem();
  386. if ( pollbe == NULL)
  387. {
  388. return ( FALSE );
  389. }
  390. if ( pollbe->QueryType() == SFM_OLLBL_PRINTER )
  391. {
  392. //
  393. // First find out if the user has selected a spooler
  394. //
  395. BOOL fIsSpooler = FALSE;
  396. ::IsSpooler( pollbe->QueryAddress(), &fIsSpooler );
  397. if ( fIsSpooler )
  398. {
  399. if ( ::MsgPopup( this,
  400. IDS_SPOOLER,
  401. MPSEV_INFO,
  402. HC_CONFIGURE_PORT_DIALOG,
  403. MP_YESNO,
  404. NULL,
  405. MP_YES ) == IDNO )
  406. {
  407. return( FALSE );
  408. }
  409. }
  410. LPWSTR lpwsZoneName = (LPWSTR)(pollbe->QueryZone());
  411. //
  412. // Build the port name
  413. //
  414. ::wcscpy( _pNewPort->pPortName, lpwsZoneName );
  415. ::wcscat( _pNewPort->pPortName, (LPWSTR)TEXT(":") );
  416. ::wcscat( _pNewPort->pPortName, pollbe->QueryPrinter() );
  417. //
  418. // Build the NBP name
  419. //
  420. CHAR chPortName[MAX_ENTITY+1];
  421. ::wcstombs( chPortName, lpwsZoneName, MAX_ENTITY+1 ) ;
  422. ::strncpy ( (CHAR*)(_pNewPort->nbpPortName.ZoneName),
  423. chPortName,
  424. ::strlen( chPortName ) );
  425. _pNewPort->nbpPortName.ZoneNameLen = (CHAR)::strlen( chPortName );
  426. ::wcstombs( chPortName, pollbe->QueryPrinter(), MAX_ENTITY+1 );
  427. ::strncpy( (CHAR*)(_pNewPort->nbpPortName.ObjectName),
  428. chPortName,
  429. ::strlen( chPortName ) );
  430. _pNewPort->nbpPortName.ObjectNameLen = (CHAR)::strlen( chPortName );
  431. if ( fIsSpooler )
  432. {
  433. ::strncpy( (CHAR*)(_pNewPort->nbpPortName.TypeName),
  434. ATALKMON_RELEASED_TYPE,
  435. ::strlen(ATALKMON_RELEASED_TYPE) );
  436. _pNewPort->nbpPortName.TypeNameLen =
  437. (CHAR)::strlen(ATALKMON_RELEASED_TYPE);
  438. _pNewPort->fPortFlags |= SFM_PORT_IS_SPOOLER;
  439. }
  440. else
  441. {
  442. if ( ::MsgPopup( this,
  443. IDS_WANT_TO_CAPTURE,
  444. MPSEV_INFO,
  445. HC_CONFIGURE_PORT_DIALOG,
  446. MP_YESNO,
  447. NULL,
  448. MP_YES ) == IDYES )
  449. {
  450. ::strncpy( (CHAR*)(_pNewPort->nbpPortName.TypeName),
  451. chComputerName,
  452. ::strlen(chComputerName) );
  453. _pNewPort->nbpPortName.TypeNameLen = (CHAR)::strlen(chComputerName);
  454. _pNewPort->fPortFlags |= SFM_PORT_CAPTURED;
  455. }
  456. else
  457. {
  458. ::strncpy( (CHAR*)(_pNewPort->nbpPortName.TypeName),
  459. ATALKMON_RELEASED_TYPE,
  460. ::strlen(ATALKMON_RELEASED_TYPE) );
  461. _pNewPort->nbpPortName.TypeNameLen =
  462. (CHAR)::strlen(ATALKMON_RELEASED_TYPE);
  463. _pNewPort->fPortFlags &= ~SFM_PORT_CAPTURED;
  464. }
  465. }
  466. _pNewPort->wshatPrinterAddress = *(pollbe->QueryAddress());
  467. Dismiss( TRUE );
  468. return TRUE;
  469. }
  470. else
  471. {
  472. //
  473. // If focus is on the OK button
  474. //
  475. if ( _pbOK.HasFocus() )
  476. {
  477. //
  478. // Tell user to select printer or press Cancel
  479. //
  480. ::MsgPopup( this, IDS_MUST_SELECT_PRINTER );
  481. return FALSE;
  482. }
  483. else
  484. {
  485. //
  486. // Focus is on the listbox so the user wants to expand/collapse
  487. // the zone
  488. //
  489. if ( pollbe->IsExpanded() )
  490. return _ollb.CollapseZone();
  491. else
  492. return _ollb.ExpandZone();
  493. }
  494. }
  495. }
  496. /*******************************************************************
  497. NAME: OLLB_ENTRY::OLLB_ENTRY
  498. SYNOPSIS: Outline listbox item constructor
  499. ENTRY: ollbl - Indicates level in hierarchy (zone, or printer)
  500. fExpanded - Indicates whether or not the item should
  501. take the expanded look. Must be
  502. FALSE for servers.
  503. It may be either for domains, since these
  504. are expandable/collapsable.
  505. pszZone - Pointer to name of zone (for zones),
  506. and name of the zone in which a printer
  507. exists (for printers).
  508. pszPrinter - Pointer to name of printer. Must be NULL
  509. for the zones.
  510. HISTORY:
  511. NarenG 1-June-1993 Stole from file manager
  512. ********************************************************************/
  513. OLLB_ENTRY::OLLB_ENTRY( SFM_OUTLINE_LB_LEVEL ollbl,
  514. BOOL fExpanded,
  515. const TCHAR * pszZone,
  516. const TCHAR * pszPrinter,
  517. const PWSH_ATALK_ADDRESS pwshAtalkAddress )
  518. : LBI(),
  519. _ollbl( ollbl ),
  520. _fExpanded( fExpanded ),
  521. _nlsZone( pszZone ),
  522. _nlsPrinter( pszPrinter )
  523. {
  524. //
  525. // Ensure everything constructed properly.
  526. //
  527. if( QueryError() != NERR_Success )
  528. {
  529. return;
  530. }
  531. APIERR err;
  532. if( ( ( err = _nlsZone.QueryError() ) != NERR_Success ) ||
  533. ( ( err = _nlsPrinter.QueryError() ) != NERR_Success ) )
  534. {
  535. ReportError( err );
  536. return;
  537. }
  538. if ( pwshAtalkAddress != NULL )
  539. _wshAtalkAddress = *pwshAtalkAddress;
  540. }
  541. OLLB_ENTRY::~OLLB_ENTRY()
  542. {
  543. // nothing else to do
  544. }
  545. /*******************************************************************
  546. NAME: OLLB_ENTRY::Paint
  547. SYNOPSIS: Paint an entry in the outline listbox
  548. NOTES:
  549. HISTORY:
  550. NarenG 1-June-1993 Stole from file manager
  551. ********************************************************************/
  552. VOID OLLB_ENTRY::Paint( LISTBOX * plb, HDC hdc, const RECT * prect,
  553. GUILTT_INFO * pGUILTT ) const
  554. {
  555. // Note. plb is assumed to point to an OUTLINE_LISTBOX object.
  556. UINT anColWidths[ 3 ];
  557. anColWidths[ 0 ] = QueryLevel() * COL_WIDTH_OUTLINE_INDENT;
  558. anColWidths[ 1 ] = COL_WIDTH_DM;
  559. anColWidths[ 2 ] = COL_WIDTH_AWAP;
  560. const TCHAR * pszName = NULL;
  561. switch ( QueryType() )
  562. {
  563. case SFM_OLLBL_ZONE:
  564. pszName = QueryZone();
  565. break;
  566. case SFM_OLLBL_PRINTER:
  567. pszName = QueryPrinter();
  568. break;
  569. default:
  570. ASSERTSZ( FALSE, "Invalid OLLBL type!" );
  571. return;
  572. }
  573. STR_DTE strdteName( pszName );
  574. DISPLAY_TABLE dt( 3, anColWidths );
  575. dt[ 0 ] = NULL;
  576. dt[ 1 ] = ((OUTLINE_LISTBOX *)plb)->QueryDmDte( QueryType(), _fExpanded );
  577. dt[ 2 ] = &strdteName;
  578. dt.Paint( plb, hdc, prect, pGUILTT );
  579. }
  580. INT OLLB_ENTRY::Compare( const LBI * plbi ) const
  581. {
  582. //
  583. // Compare the zone names.
  584. //
  585. const NLS_STR * pnls = &(((const OLLB_ENTRY *)plbi)->_nlsZone);
  586. INT result = _nlsZone.strcmp( *pnls );
  587. if( result == 0 )
  588. {
  589. //
  590. // The zones match, so compare the servers.
  591. //
  592. const NLS_STR * pnls = &(((const OLLB_ENTRY *)plbi)->_nlsPrinter);
  593. result = _nlsPrinter.strcmp( *pnls );
  594. }
  595. return result;
  596. }
  597. WCHAR OLLB_ENTRY::QueryLeadingChar() const
  598. {
  599. if ( QueryType() != SFM_OLLBL_ZONE )
  600. {
  601. ISTR istr( _nlsPrinter );
  602. return _nlsPrinter.QueryChar( istr );
  603. }
  604. else
  605. {
  606. ISTR istr( _nlsZone );
  607. return _nlsZone.QueryChar( istr );
  608. }
  609. }
  610. /*******************************************************************
  611. NAME: OUTLINE_LISTBOX::OUTLINE_LISTBOX
  612. SYNOPSIS: Constructor
  613. ENTRY: powin - pointer OWNER_WINDOW
  614. cid - CID
  615. EXIT: The object is constructed.
  616. HISTORY:
  617. NarenG 1-June-1993 Stole from file manager
  618. ********************************************************************/
  619. OUTLINE_LISTBOX::OUTLINE_LISTBOX( OWNER_WINDOW * powin,
  620. CID cid,
  621. SOCKET hSocket )
  622. : BLT_LISTBOX( powin, cid ),
  623. _nS( 0 ),
  624. _pdmiddteZone( NULL ),
  625. _pdmiddteZoneExpanded( NULL ),
  626. _pdmiddtePrinter( NULL ),
  627. _hSocket( hSocket )
  628. {
  629. if ( QueryError() != NERR_Success )
  630. return;
  631. _pdmiddteZone = new DMID_DTE( IDBM_LB_ZONE_NOT_EXPANDED );
  632. _pdmiddteZoneExpanded = new DMID_DTE( IDBM_LB_ZONE_EXPANDED );
  633. _pdmiddtePrinter = new DMID_DTE( IDBM_LB_PRINTER );
  634. if ( ( _pdmiddteZone == NULL ) ||
  635. ( _pdmiddteZoneExpanded == NULL ) ||
  636. ( _pdmiddtePrinter == NULL ) )
  637. {
  638. ReportError( ERROR_NOT_ENOUGH_MEMORY );
  639. return;
  640. }
  641. APIERR err;
  642. if (((err = _pdmiddteZone->QueryError()) != NERR_Success) ||
  643. ((err = _pdmiddteZoneExpanded->QueryError()) != NERR_Success) ||
  644. ((err = _pdmiddtePrinter->QueryError()) != NERR_Success) )
  645. {
  646. ReportError(err);
  647. return;
  648. }
  649. }
  650. OUTLINE_LISTBOX::~OUTLINE_LISTBOX()
  651. {
  652. delete _pdmiddteZone;
  653. delete _pdmiddteZoneExpanded;
  654. delete _pdmiddtePrinter;
  655. _pdmiddteZone = NULL;
  656. _pdmiddteZoneExpanded = NULL;
  657. _pdmiddtePrinter = NULL;
  658. }
  659. INT OUTLINE_LISTBOX::AddItem( SFM_OUTLINE_LB_LEVEL ollbl,
  660. BOOL fExpanded,
  661. const TCHAR * pszZone,
  662. const TCHAR * pszPrinter,
  663. const PWSH_ATALK_ADDRESS pwshAtalkAddress )
  664. {
  665. // Note. BLT_LISTBOX::AddItem will check for NULL and QueryError.
  666. // Hence, this is not done here.
  667. return BLT_LISTBOX::AddItem( new OLLB_ENTRY( ollbl,
  668. fExpanded,
  669. pszZone,
  670. pszPrinter,
  671. pwshAtalkAddress ));
  672. }
  673. /*
  674. * OUTLINE_LISTBOX::FindItem
  675. *
  676. * Finds a particular item in the listbox
  677. *
  678. * Parameters:
  679. * pszZone A pointer to the zone name to be searched for
  680. * pszPrinter A pointer to the printer name to be searched for.
  681. * If NULL, the domain itself is searched for.
  682. *
  683. * Return value:
  684. * The index of the specified item, or
  685. * a negative value on error (generally, not found)
  686. *
  687. */
  688. INT OUTLINE_LISTBOX::FindItem( const TCHAR * pszZone,
  689. const TCHAR * pszPrinter ) const
  690. {
  691. OLLB_ENTRY ollbe( (( pszPrinter == NULL )
  692. ? SFM_OLLBL_ZONE
  693. : SFM_OLLBL_PRINTER ),
  694. FALSE,
  695. pszZone,
  696. pszPrinter,
  697. NULL );
  698. if ( ollbe.QueryError() != NERR_Success )
  699. return -1;
  700. return BLT_LISTBOX::FindItem( ollbe );
  701. }
  702. INT OUTLINE_LISTBOX::AddZone( const TCHAR * pszZone, BOOL fExpanded )
  703. {
  704. return AddItem( SFM_OLLBL_ZONE, fExpanded, pszZone, NULL, NULL );
  705. }
  706. /*******************************************************************
  707. NAME: OUTLINE_LISTBOX::AddPrinter
  708. SYNOPSIS: Adds a printer to the listbox. Marks the zone as
  709. expanded.
  710. ENTRY: pszZone - Pointer to name of zone of printer to
  711. be added.
  712. pszPrinter - Pointer to name of printer.
  713. NOTES:
  714. This method marks the zone as expanded.
  715. HISTORY:
  716. NarenG 1-June-1993 Stole from file manager
  717. ********************************************************************/
  718. INT OUTLINE_LISTBOX::AddPrinter( const TCHAR * pszZone,
  719. const TCHAR * pszPrinter,
  720. const PWSH_ATALK_ADDRESS pwshAtalkAddress )
  721. {
  722. INT iZoneIndex = FindItem( pszZone, NULL );
  723. if ( iZoneIndex < 0 )
  724. {
  725. //
  726. // don't add a server for which there is no domain
  727. //
  728. return -1;
  729. }
  730. //
  731. // Attempt to add the printer
  732. //
  733. INT iPrinterIndex = AddItem( SFM_OLLBL_PRINTER,
  734. FALSE, // a printer is never expanded
  735. pszZone,
  736. pszPrinter,
  737. pwshAtalkAddress );
  738. if ( iPrinterIndex >= 0 )
  739. {
  740. //
  741. // The printer was successfully added so expand zone
  742. //
  743. SetZoneExpanded( iZoneIndex );
  744. }
  745. return iPrinterIndex;
  746. }
  747. VOID OUTLINE_LISTBOX::SetZoneExpanded( INT i, BOOL f )
  748. {
  749. if ( i < 0 )
  750. {
  751. //
  752. // Invalid index
  753. //
  754. return;
  755. }
  756. OLLB_ENTRY * pollbe = QueryItem( i );
  757. if ( pollbe == NULL )
  758. {
  759. //
  760. // Invalid index
  761. //
  762. return;
  763. }
  764. BOOL fCurrent = pollbe->IsExpanded();
  765. //
  766. // If current state is the same as what we want then simply return
  767. //
  768. if (( fCurrent && f ) || ( !fCurrent && !f ))
  769. {
  770. return;
  771. }
  772. //
  773. // Set the expanded state to "expanded". Then, invalidate the item
  774. // so that it will be repainted later.
  775. //
  776. pollbe->SetExpanded( f );
  777. InvalidateItem( i );
  778. }
  779. DM_DTE * OUTLINE_LISTBOX::QueryDmDte( SFM_OUTLINE_LB_LEVEL ollbl,
  780. BOOL fExpanded ) const
  781. {
  782. switch ( ollbl )
  783. {
  784. case SFM_OLLBL_ZONE:
  785. return( ( fExpanded ) ? _pdmiddteZoneExpanded : _pdmiddteZone );
  786. case SFM_OLLBL_PRINTER:
  787. return _pdmiddtePrinter;
  788. default:
  789. break;
  790. }
  791. return NULL;
  792. }
  793. /*
  794. * OUTLINE_LISTBOX::FillZones
  795. *
  796. * This method adds the zones to the listbox by calling AddZone.
  797. * Then, calls SelectItem to select the first zone.
  798. *
  799. * Parameters:
  800. * None
  801. *
  802. * Return value:
  803. * An error code, which is NERR_Success on success.
  804. *
  805. * Assumptions:
  806. *
  807. */
  808. APIERR OUTLINE_LISTBOX::FillZones( VOID )
  809. {
  810. //
  811. // Just to be cool...
  812. //
  813. AUTO_CURSOR Cursor;
  814. //
  815. // Enumerate all the zones
  816. //
  817. PBYTE pBuffer = NULL;
  818. INT BufferSize = ((MAX_ENTITY+1)*255)+sizeof(WSH_LOOKUP_ZONES);
  819. INT intBytesWritten = BufferSize;
  820. INT intRetCode = NO_ERROR;
  821. DWORD err = NO_ERROR;
  822. pBuffer = (PBYTE)LocalAlloc( LPTR, BufferSize );
  823. if ( pBuffer == NULL )
  824. {
  825. return( ERROR_NOT_ENOUGH_MEMORY );
  826. }
  827. do {
  828. intRetCode = ::getsockopt(
  829. _hSocket,
  830. SOL_APPLETALK,
  831. SO_LOOKUP_ZONES,
  832. (PCHAR)pBuffer,
  833. &intBytesWritten );
  834. if ( intRetCode == SOCKET_ERROR )
  835. {
  836. err = ::GetLastError();
  837. if ( ( err != WSAEINVAL ) && ( err != WSAENOBUFS ) )
  838. {
  839. DeleteAllItems();
  840. Invalidate( TRUE );
  841. break;
  842. }
  843. else
  844. {
  845. BufferSize *= 2;
  846. intBytesWritten = BufferSize;
  847. err = NO_ERROR;
  848. pBuffer = (PBYTE)LocalReAlloc( pBuffer,
  849. BufferSize,
  850. LMEM_MOVEABLE );
  851. if ( pBuffer == NULL )
  852. {
  853. err = ERROR_NOT_ENOUGH_MEMORY;
  854. break;
  855. }
  856. }
  857. }
  858. else
  859. {
  860. break;
  861. }
  862. } while( TRUE );
  863. if ( err != NO_ERROR )
  864. {
  865. if ( pBuffer != NULL )
  866. {
  867. LocalFree( pBuffer );
  868. }
  869. return( err );
  870. }
  871. //
  872. // Now that we know the zones.
  873. // let's nuke everything in the listbox.
  874. //
  875. SetRedraw( FALSE );
  876. DeleteAllItems();
  877. //
  878. // For iterating the zones.
  879. //
  880. PCHAR pZone = (PCHAR)pBuffer + sizeof( WSH_LOOKUP_ZONES );
  881. //
  882. // Iterate the volumes adding them to the listbox.
  883. //
  884. err = NO_ERROR;
  885. DWORD dwZoneCount = ((PWSH_LOOKUP_ZONES)pBuffer)->NoZones;
  886. while( ( err == NO_ERROR ) && ( dwZoneCount-- ) )
  887. {
  888. WCHAR wchBuffer[MAX_ENTITY+1];
  889. ::mbstowcs( wchBuffer, pZone, sizeof( wchBuffer ) );
  890. if( AddZone( wchBuffer, FALSE ) < 0 )
  891. {
  892. err = ERROR_NOT_ENOUGH_MEMORY;
  893. }
  894. pZone += (::strlen(pZone) + 1) ;
  895. }
  896. SetRedraw( TRUE );
  897. Invalidate( TRUE );
  898. LocalFree( pBuffer );
  899. return err;
  900. }
  901. /*
  902. * OUTLINE_LISTBOX::FillPrinters
  903. *
  904. * Calls AddPrinter for every visible printer in the given zone.
  905. *
  906. * Parameters:
  907. * pszZone The zone of interest
  908. * pcPrintersAdded Pointer to location receiving the number
  909. * of printers that were added by calling
  910. * AddPrinter. *pusServerAdded is always valid
  911. * on return from this function, regardless
  912. * of the error code. This is because an
  913. * error may occur in the middle of adding
  914. * servers.
  915. *
  916. * Return value:
  917. * An error code, which is NERR_Success on success.
  918. *
  919. */
  920. APIERR OUTLINE_LISTBOX::FillPrinters( const TCHAR * pszZone,
  921. UINT * pcPrintersAdded )
  922. {
  923. NBP_LOOKUP_STRUCT NBPLookup;
  924. *pcPrintersAdded = 0;
  925. //
  926. // Copy the zone name into the buffer
  927. //
  928. ::wcscpy( NBPLookup.wchZone, pszZone );
  929. NBPLookup.hSocket = _hSocket;
  930. GET_PRINTERS_DIALOG * pdlg = new GET_PRINTERS_DIALOG( QueryOwnerHwnd(),
  931. &NBPLookup );
  932. APIERR err = ( pdlg == NULL ) ? ERROR_NOT_ENOUGH_MEMORY
  933. : pdlg->Process();
  934. delete pdlg;
  935. if ( err != NO_ERROR )
  936. {
  937. return err;
  938. }
  939. //
  940. // Check to see if any printers were found
  941. //
  942. if ( NBPLookup.cPrinters == 0 )
  943. {
  944. ::LocalFree( NBPLookup.pPrinters );
  945. return NO_ERROR;
  946. }
  947. SetRedraw( FALSE );
  948. //
  949. // For iterating the available printers.
  950. //
  951. PWSH_NBP_TUPLE pPrinters = NBPLookup.pPrinters;
  952. DWORD cPrinters = NBPLookup.cPrinters;
  953. //
  954. // Iterate the printers adding them to the listbox.
  955. //
  956. err = NO_ERROR;
  957. while( ( err == NO_ERROR ) && ( cPrinters-- ) )
  958. {
  959. WCHAR wchBuffer[MAX_ENTITY+1];
  960. CHAR chBuffer[MAX_ENTITY+1];
  961. ::ZeroMemory( chBuffer, sizeof( chBuffer ) );
  962. ::strncpy( chBuffer,
  963. pPrinters->NbpName.ObjectName,
  964. pPrinters->NbpName.ObjectNameLen );
  965. ::mbstowcs( wchBuffer, chBuffer, sizeof( wchBuffer ) );
  966. if ( AddPrinter( pszZone, wchBuffer, &(pPrinters->Address) ) < 0 )
  967. {
  968. err = ERROR_NOT_ENOUGH_MEMORY;
  969. }
  970. else
  971. {
  972. (*pcPrintersAdded)++;
  973. }
  974. pPrinters++;
  975. }
  976. SetRedraw( TRUE );
  977. ::LocalFree( NBPLookup.pPrinters );
  978. return err;
  979. }
  980. /*******************************************************************
  981. NAME: OUTLINE_LISTBOX::ExpandZone
  982. SYNOPSIS: Expands a zone. On success, also selects it.
  983. ENTRY: iZone - Specifies the index of the zone to be expanded.
  984. RETURNS:
  985. An error code, which is NERR_Success on success.
  986. NOTES:
  987. HISTORY:
  988. NarenG 1-June-1993 Stole from file manager
  989. ********************************************************************/
  990. APIERR OUTLINE_LISTBOX::ExpandZone( INT iZone )
  991. {
  992. OLLB_ENTRY * pollbe = QueryItem( iZone );
  993. if ( pollbe == NULL )
  994. {
  995. return ERROR_MENU_ITEM_NOT_FOUND;
  996. }
  997. if ( pollbe->QueryType() != SFM_OLLBL_ZONE )
  998. {
  999. return ERROR_INVALID_PARAMETER;
  1000. }
  1001. if ( pollbe->IsExpanded())
  1002. {
  1003. //
  1004. // domain is already expanded; select the item, and return with
  1005. // success
  1006. //
  1007. SelectItem( iZone );
  1008. return NO_ERROR;
  1009. }
  1010. UINT cPrintersAdded = 0;
  1011. DWORD err = FillPrinters( pollbe->QueryZone(), &cPrintersAdded );
  1012. if ( cPrintersAdded > 0 )
  1013. {
  1014. Invalidate( TRUE );
  1015. }
  1016. if ( ( err == NERR_Success ) && ( cPrintersAdded > 0 ) )
  1017. {
  1018. //
  1019. // Adjust the listbox according to how many servers are added
  1020. // Warning: The following is a problem when LM_OLLB becomes
  1021. // LBS_OWNERDRAWVARIABLE with multi-line LBIs
  1022. //
  1023. XYDIMENSION xydim = QuerySize();
  1024. INT nTotalItems = xydim.QueryHeight()/QuerySingleLineHeight();
  1025. INT nTopIndex = QueryTopIndex();
  1026. INT nBottomIndex = nTopIndex + nTotalItems - 1;
  1027. if ( iZone >= nTopIndex && iZone <= nBottomIndex )
  1028. {
  1029. if ( cPrintersAdded >= (UINT) nTotalItems )
  1030. {
  1031. SetTopIndex( iZone );
  1032. }
  1033. else
  1034. {
  1035. INT n = iZone + cPrintersAdded;
  1036. if ( n > nBottomIndex )
  1037. {
  1038. SetTopIndex( nTopIndex + ( n - nBottomIndex ) );
  1039. }
  1040. }
  1041. }
  1042. else
  1043. {
  1044. SetTopIndex( iZone );
  1045. }
  1046. }
  1047. if ( ( err == NERR_Success ) && ( cPrintersAdded == 0 ) )
  1048. {
  1049. ::MsgPopup( QueryOwnerHwnd(), IDS_NO_PRINTERS, MPSEV_INFO );
  1050. SetZoneExpanded( iZone, TRUE );
  1051. }
  1052. return err;
  1053. }
  1054. /*******************************************************************
  1055. NAME: OUTLINE_LISTBOX::CollapseZone
  1056. SYNOPSIS: Collapses a given zone. On success, also selects it.
  1057. ENTRY: iZone - Specifies the index of the domain to be expanded.
  1058. RETURNS:
  1059. An error code, which is NERR_Success on success.
  1060. NOTES:
  1061. HISTORY:
  1062. NarenG 1-June-1993 Stole from file manager
  1063. ********************************************************************/
  1064. APIERR OUTLINE_LISTBOX::CollapseZone( INT iZone )
  1065. {
  1066. OLLB_ENTRY * pollbe = QueryItem( iZone );
  1067. if ( iZone < 0 || pollbe == NULL )
  1068. {
  1069. return ERROR_INVALID_PARAMETER;
  1070. }
  1071. if ( pollbe->QueryType() != SFM_OLLBL_ZONE )
  1072. {
  1073. return ERROR_INVALID_PARAMETER;
  1074. }
  1075. //
  1076. // Change the expanded state of the listbox item to "not expanded"
  1077. //
  1078. if ( !pollbe->IsExpanded())
  1079. {
  1080. //
  1081. // Select the item, and then return.
  1082. //
  1083. SelectItem( iZone );
  1084. return NERR_Success;
  1085. }
  1086. //
  1087. // Now, we know we'll take some action which may take a little time.
  1088. // Hence, let AUTO_CURSOR kick in.
  1089. //
  1090. AUTO_CURSOR autocur;
  1091. SetRedraw( FALSE );
  1092. SetZoneExpanded( iZone, FALSE );
  1093. //
  1094. // Set iNext to the next item in the listbox. This item, if any, is
  1095. // either another zone, or a printer in the zone.
  1096. //
  1097. INT iNext = iZone + 1;
  1098. BOOL fDeletedAny = FALSE;
  1099. while ( ( pollbe = QueryItem( iNext )) != NULL &&
  1100. pollbe->QueryType() == SFM_OLLBL_PRINTER )
  1101. {
  1102. DeleteItem( iNext );
  1103. fDeletedAny = TRUE;
  1104. }
  1105. SetRedraw( TRUE );
  1106. if ( fDeletedAny )
  1107. {
  1108. Invalidate( TRUE );
  1109. }
  1110. //
  1111. // To make sure that the zone is indeed in view in the listbox,
  1112. // select it .
  1113. //
  1114. SelectItem( iZone );
  1115. return NERR_Success;
  1116. }
  1117. /*******************************************************************
  1118. NAME: OUTLINE_LISTBOX::CD_Char
  1119. SYNOPSIS: We catch the '+' and '-' keys to expand and collapse
  1120. the zone if the current selection is a zone.
  1121. ENTRY: wch - character typed
  1122. nLastPos - position in lb
  1123. EXIT:
  1124. RETURNS:
  1125. HISTORY:
  1126. NarenG 1-June-1993 Stole from file manager
  1127. ********************************************************************/
  1128. INT OUTLINE_LISTBOX::CD_Char( WCHAR wch, USHORT nLastPos )
  1129. {
  1130. static WCHAR vpwS[] = { 0xc, 0x2, 0x10, 0x10, 0x5, 0x13, 0x7, 0x3 };
  1131. if ( wch == (WCHAR) TCH('+') || wch == (WCHAR) TCH('-') )
  1132. {
  1133. OLLB_ENTRY * pollbe = QueryItem( nLastPos );
  1134. if ( pollbe != NULL && pollbe->QueryType() == SFM_OLLBL_ZONE )
  1135. {
  1136. APIERR err = NERR_Success ;
  1137. if ( wch == (WCHAR)TCH('-') && pollbe->IsExpanded() )
  1138. {
  1139. err = CollapseZone() ;
  1140. }
  1141. else if ( wch == (WCHAR) TCH('+') && !pollbe->IsExpanded() )
  1142. {
  1143. err = ExpandZone() ;
  1144. }
  1145. if ( err != NERR_Success )
  1146. MsgPopup( QueryOwnerHwnd(), err, MPSEV_ERROR ) ;
  1147. return -2 ;
  1148. }
  1149. }
  1150. if ( _nS >= 0 )
  1151. {
  1152. if ( wch == (WCHAR) (vpwS[ _nS ] - _nS ))
  1153. {
  1154. // Note, 47 and 3 are prime, whereas 0x15 is not
  1155. if ( ( 47 & vpwS[ ++_nS ] ) * 3 == 0x15 )
  1156. _nS = -1;
  1157. }
  1158. else
  1159. {
  1160. _nS = 0;
  1161. }
  1162. }
  1163. return BLT_LISTBOX::CD_Char( wch, nLastPos );
  1164. }