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.

3522 lines
76 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. All rights reserved.
  4. Module Name:
  5. svrprop.cxx
  6. Abstract:
  7. Server Properties
  8. Author:
  9. Steve Kiraly (SteveKi) 11/15/95
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "psetup.hxx"
  15. #include "drvver.hxx"
  16. #include "drvsetup.hxx"
  17. #include "portslv.hxx"
  18. #include "portdlg.hxx"
  19. #include "driverif.hxx"
  20. #include "driverlv.hxx"
  21. #include "driverdt.hxx"
  22. #include "svrprop.hxx"
  23. #include "forms.hxx"
  24. #include "time.hxx"
  25. #include "instarch.hxx"
  26. #include "dsinterf.hxx"
  27. #include "prtprop.hxx"
  28. #include "archlv.hxx"
  29. #include "detect.hxx"
  30. #include "setup.hxx"
  31. #include "prndata.hxx"
  32. #include "persist.hxx"
  33. /*++
  34. Routine Description:
  35. WOW64 version.
  36. see vServerPropPages below.
  37. Arguments:
  38. see vServerPropPages below.
  39. Return Value:
  40. --*/
  41. VOID
  42. vServerPropPagesWOW64(
  43. IN HWND hwnd,
  44. IN LPCTSTR pszServerName,
  45. IN INT iCmdShow,
  46. IN LPARAM lParam
  47. )
  48. {
  49. //
  50. // This function potentially may load the driver UI so we call a private API
  51. // exported by winspool.drv, which will RPC the call to a special 64 bit surrogate
  52. // process where the 64 bit driver can be loaded.
  53. //
  54. CDllLoader dll(TEXT("winspool.drv"));
  55. if (dll)
  56. {
  57. ptr_PrintUIServerPropPages pfn =
  58. (ptr_PrintUIServerPropPages )dll.GetProcAddress(ord_PrintUIServerPropPages);
  59. if (pfn)
  60. {
  61. // call into winspool.drv
  62. pfn(hwnd, pszServerName, iCmdShow, lParam);
  63. }
  64. }
  65. }
  66. /*++
  67. Routine Description:
  68. Native version.
  69. see vServerPropPages below.
  70. Arguments:
  71. see vServerPropPages below.
  72. Return Value:
  73. --*/
  74. VOID
  75. vServerPropPagesNative(
  76. IN HWND hwnd,
  77. IN LPCTSTR pszServerName,
  78. IN INT iCmdShow,
  79. IN LPARAM lParam
  80. )
  81. {
  82. DBGMSG( DBG_TRACE, ( "vServerPropPages\n") );
  83. BOOL bModal = FALSE;
  84. DWORD dwSheetNumber = LOWORD( lParam );
  85. //
  86. // If the high word is non zero then dialog is modal.
  87. //
  88. if( HIWORD( lParam ) ) {
  89. bModal = TRUE;
  90. }
  91. //
  92. // Create the server specific data.
  93. //
  94. TServerData *pServerData = new TServerData( pszServerName,
  95. iCmdShow,
  96. dwSheetNumber,
  97. hwnd,
  98. bModal );
  99. //
  100. // If errors were encountered creating document data.
  101. //
  102. if( !VALID_PTR( pServerData )){
  103. goto Fail;
  104. }
  105. //
  106. // If lparam is has the high word non zero the dialog is modal.
  107. //
  108. if( bModal ) {
  109. //
  110. // If a failure occured then the message has already been displayed,
  111. // therefore we just exit.
  112. //
  113. iServerPropPagesProc( pServerData );
  114. return;
  115. } else {
  116. //
  117. // Create the thread which handles the UI. iServerPropPagesProc adopts
  118. // pServerData, therefore only on thread creation failure do we
  119. // release the data back to the heap.
  120. //
  121. DWORD dwIgnore;
  122. HANDLE hThread;
  123. hThread = TSafeThread::Create( NULL,
  124. 0,
  125. (LPTHREAD_START_ROUTINE)iServerPropPagesProc,
  126. pServerData,
  127. 0,
  128. &dwIgnore );
  129. //
  130. // Check thread creation.
  131. //
  132. if( !hThread ){
  133. goto Fail;
  134. }
  135. //
  136. // Thread handle is not needed.
  137. //
  138. CloseHandle( hThread );
  139. return;
  140. }
  141. Fail:
  142. if( !pServerData ){
  143. vShowResourceError( hwnd );
  144. } else {
  145. iMessage( hwnd,
  146. IDS_SERVER_PROPERTIES_TITLE,
  147. IDS_ERR_SERVER_PROP_CANNOT_VIEW,
  148. MB_OK|MB_ICONSTOP,
  149. kMsgGetLastError,
  150. NULL );
  151. }
  152. delete pServerData;
  153. }
  154. /*++
  155. Routine Description:
  156. This function opens the property sheet of specified server.
  157. We can't guarentee that this propset will perform all lengthy
  158. operations in a worker thread (we synchronously call things like
  159. ConfigurePort). Therefore, we spawn off a separate thread to
  160. handle document properties.
  161. Arguments:
  162. hwnd - Specifies the parent window (optional).
  163. pszPrinter - Specifies the printer name (e.g., "My HP LaserJet IIISi").
  164. nCmdShow - Initial show state
  165. lParam - May specify a sheet number to open to or if the high word
  166. is non zero then dialog is modal.
  167. Return Value:
  168. --*/
  169. VOID
  170. vServerPropPages(
  171. IN HWND hwnd,
  172. IN LPCTSTR pszServerName,
  173. IN INT iCmdShow,
  174. IN LPARAM lParam
  175. )
  176. {
  177. if (IsRunningWOW64())
  178. {
  179. vServerPropPagesWOW64(hwnd, pszServerName, iCmdShow, lParam);
  180. }
  181. else
  182. {
  183. vServerPropPagesNative(hwnd, pszServerName, iCmdShow, lParam);
  184. }
  185. }
  186. /*++
  187. aRoutine Name:
  188. iServerPropPagesProc
  189. Routine Description:
  190. This is the routine called by the create thread call to display the
  191. server property sheets.
  192. Arguments:
  193. pServerData - Pointer to the Server data set used by all property sheets.
  194. Return Value:
  195. TRUE - if the property sheets were displayed.
  196. FALSE - error creating and displaying property sheets.
  197. --*/
  198. INT WINAPI
  199. iServerPropPagesProc(
  200. IN TServerData *pServerData ADOPT
  201. )
  202. {
  203. DBGMSG( DBG_TRACE, ( "iServerPropPagesProc\n") );
  204. BOOL bStatus = pServerData->bRegisterWindow( PRINTER_PIDL_TYPE_PROPERTIES );
  205. if( bStatus ){
  206. //
  207. // Check if the window is already present.
  208. //
  209. if( pServerData->bIsWindowPresent() ){
  210. DBGMSG( DBG_TRACE, ( "iServerPropPagesProc: currently running.\n" ) );
  211. bStatus = FALSE;
  212. }
  213. }
  214. if( bStatus ) {
  215. bStatus = pServerData->bLoad();
  216. if( !bStatus ){
  217. iMessage( pServerData->_hwnd,
  218. IDS_SERVER_PROPERTIES_TITLE,
  219. IDS_ERR_SERVER_PROP_CANNOT_VIEW,
  220. MB_OK|MB_ICONSTOP|MB_SETFOREGROUND,
  221. kMsgGetLastError,
  222. NULL );
  223. } else {
  224. //
  225. // Create the Server property sheet windows.
  226. //
  227. TServerWindows ServerWindows( pServerData );
  228. //
  229. // Were the document windows create
  230. //
  231. if( !VALID_OBJ( ServerWindows ) ){
  232. iMessage( pServerData->_hwnd,
  233. IDS_SERVER_PROPERTIES_TITLE,
  234. IDS_ERR_SERVER_PROP_CANNOT_VIEW,
  235. MB_OK|MB_ICONSTOP|MB_SETFOREGROUND,
  236. kMsgGetLastError,
  237. NULL );
  238. bStatus = FALSE;
  239. }
  240. //
  241. // Build the property pages.
  242. //
  243. if( bStatus ){
  244. if( !ServerWindows.bBuildPages( ) ){
  245. vShowResourceError( NULL );
  246. bStatus = FALSE;
  247. }
  248. }
  249. //
  250. // Display the property pages.
  251. //
  252. if( bStatus ){
  253. if( !ServerWindows.bDisplayPages( ) ){
  254. vShowResourceError( NULL );
  255. bStatus = FALSE;
  256. }
  257. }
  258. }
  259. }
  260. //
  261. // Ensure we release the document data.
  262. // We have adopted pSeverData, so we must free it.
  263. //
  264. delete pServerData;
  265. return bStatus;
  266. }
  267. /*++
  268. Routine Name:
  269. TServerData
  270. Routine Description:
  271. Server data property sheet constructor.
  272. Arguments:
  273. pszPrinterName - Name of printer or queue where jobs reside.
  274. JobId - Job id to display properties of.
  275. iCmdShow - Show dialog style.
  276. lParam - Indicates which page to display initialy
  277. Return Value:
  278. Nothing.
  279. --*/
  280. TServerData::
  281. TServerData(
  282. IN LPCTSTR pszServerName,
  283. IN INT iCmdShow,
  284. IN LPARAM lParam,
  285. IN HWND hwnd,
  286. IN BOOL bModal
  287. ) : MSingletonWin( pszServerName, hwnd, bModal ),
  288. _iCmdShow( iCmdShow ),
  289. _uStartPage( (UINT)lParam ),
  290. _bValid( FALSE ),
  291. _hPrintServer( NULL ),
  292. _hDefaultSmallIcon( NULL ),
  293. _bCancelButtonIsClose( FALSE ),
  294. _dwDriverVersion( 0 ),
  295. _bRemoteDownLevel( FALSE ),
  296. _bRebootRequired( FALSE )
  297. {
  298. if( !MSingletonWin::bValid( )){
  299. return;
  300. }
  301. //
  302. // Retrieve icons.
  303. //
  304. LoadPrinterIcons( _strPrinterName, NULL, &_hDefaultSmallIcon );
  305. SPLASSERT( _hDefaultSmallIcon );
  306. //
  307. // Set the server name to NULL if it's local.
  308. //
  309. _pszServerName = _strPrinterName.bEmpty() ? NULL : (LPCTSTR)_strPrinterName;
  310. //
  311. // Get the machine name.
  312. //
  313. vCreateMachineName( _strPrinterName,
  314. _pszServerName ? FALSE : TRUE,
  315. _strMachineName );
  316. //
  317. // Get the print servers driver version, the driver
  318. // version corresponds to the actual spooler version, we
  319. // are using this for downlevel detection.
  320. //
  321. if( !bGetCurrentDriver( _pszServerName, &_dwDriverVersion ) )
  322. {
  323. //
  324. // Note this is not a fatal error, we won't have the
  325. // add/delete/configure ports buttons enabled.
  326. //
  327. DBGMSG( DBG_WARN, ( "Get driver version failed.\n" ) );
  328. }
  329. //
  330. // Check if we are remotely administering a downlevel machine
  331. //
  332. _bRemoteDownLevel = ( bIsRemote( _pszServerName ) && ( GetDriverVersion( _dwDriverVersion ) <= 2 ) ) ? TRUE : FALSE;
  333. _bValid = TRUE;
  334. }
  335. /*++
  336. Routine Name:
  337. ~TServerData
  338. Routine Description:
  339. Stores the document data back to the server.
  340. Arguments:
  341. None.
  342. Return Value:
  343. Nothing.
  344. --*/
  345. TServerData::
  346. ~TServerData(
  347. VOID
  348. )
  349. {
  350. //
  351. // Insure we close the print server.
  352. //
  353. if( _hPrintServer ){
  354. ClosePrinter( _hPrintServer );
  355. }
  356. //
  357. // Destroy the printer icon.
  358. //
  359. if( _hDefaultSmallIcon ){
  360. DestroyIcon( _hDefaultSmallIcon );
  361. }
  362. }
  363. /*++
  364. Routine Name:
  365. bValid
  366. Routine Description:
  367. Returns objects state.
  368. Arguments:
  369. None.
  370. Return Value:
  371. TRUE object is in valid state, FALSE object is not valid.
  372. --*/
  373. BOOL
  374. TServerData::
  375. bValid(
  376. VOID
  377. )
  378. {
  379. return _bValid;
  380. }
  381. /*++
  382. Routine Name:
  383. vCreateMachineName
  384. Routine Description:
  385. Create the machine name for display. bLocal indicates the
  386. provided server name is for the local machine, Since a
  387. local machine is often represented by the NULL pointer we
  388. will get the computer name if a local server name is passed. If the
  389. bLocal is false strPrinterName contains the name of the remote
  390. printer server.
  391. Arguments:
  392. strServerName - Name of the print server.
  393. bLocal - TRUE str server name is local, or FALSE strPrinterName is name of
  394. remote print server.
  395. strMachineName - Target of the fetched machine name.
  396. Return Value:
  397. Nothing.
  398. --*/
  399. VOID
  400. TServerData::
  401. vCreateMachineName(
  402. IN const TString &strServerName,
  403. IN BOOL bLocal,
  404. IN TString &strMachineName
  405. )
  406. {
  407. TStatusB bStatus;
  408. LPCTSTR pszBuffer;
  409. //
  410. // If a server name was provided then set the title to
  411. // the server name, otherwise get the computer name.
  412. //
  413. if( !bLocal ){
  414. //
  415. // Copy the server name.
  416. //
  417. bStatus DBGCHK = strMachineName.bUpdate( strServerName );
  418. } else {
  419. //
  420. // Server name is null, therefore it is the local machine.
  421. //
  422. bStatus DBGCHK = bGetMachineName( strMachineName );
  423. }
  424. //
  425. // Remove any leading slashes.
  426. //
  427. pszBuffer = (LPCTSTR)strMachineName;
  428. for( ; pszBuffer && (*pszBuffer == TEXT( '\\' )); pszBuffer++ )
  429. ;
  430. //
  431. // Update the name we display on the sheets.
  432. //
  433. bStatus DBGCHK = strMachineName.bUpdate( pszBuffer );
  434. }
  435. /*++
  436. Routine Name:
  437. bLoad
  438. Routine Description:
  439. Loads the property sheet specific data.
  440. Arguments:
  441. None.
  442. Return Value:
  443. TRUE - Data loaded successfully,
  444. FALSE - Data was not loaded.
  445. --*/
  446. BOOL
  447. TServerData::
  448. bLoad(
  449. VOID
  450. )
  451. {
  452. DBGMSG( DBG_TRACE, ( "TServerData::bLoad\n") );
  453. //
  454. // Attempt to open print server with full access.
  455. //
  456. TStatus Status;
  457. DWORD dwAccess = 0;
  458. Status DBGCHK = TPrinter::sOpenPrinter( pszServerName(),
  459. &dwAccess,
  460. &_hPrintServer );
  461. if( Status == ERROR_SUCCESS ){
  462. //
  463. // Save administrator capability flag.
  464. //
  465. bAdministrator() = (dwAccess == SERVER_ALL_ACCESS);
  466. //
  467. // Get the default title from the resource file.
  468. //
  469. if( !_strTitle.bLoadString( ghInst, IDS_SERVER_SETTINGS_TITLE ) ){
  470. DBGMSG( DBG_WARN, ( "strTitle().bLoadString failed with %d\n", GetLastError () ) );
  471. vShowResourceError( hwnd() );
  472. }
  473. //
  474. // Null terminate the title buffer.
  475. //
  476. TCHAR szTitle[kStrMax+kPrinterBufMax] = {0};
  477. UINT nSize = COUNTOF( szTitle );
  478. //
  479. // Create the property sheet title.
  480. //
  481. if( pszServerName() ){
  482. _tcscpy( szTitle, pszServerName() );
  483. _tcscat( szTitle, TEXT( "\\" ) );
  484. }
  485. //
  486. // Build the title buffer.
  487. //
  488. _tcscat( szTitle, _strTitle );
  489. //
  490. // Format the title similar to the shell.
  491. //
  492. ConstructPrinterFriendlyName( szTitle, szTitle, &nSize );
  493. //
  494. // Update the property sheet title.
  495. //
  496. if( !_strTitle.bUpdate( szTitle ) ){
  497. DBGMSG( DBG_WARN, ( "strTitle().bUpdate failed with %d\n", GetLastError () ) );
  498. vShowResourceError( hwnd() );
  499. }
  500. }
  501. return Status == ERROR_SUCCESS;
  502. }
  503. /*++
  504. Routine Name:
  505. bStore
  506. Routine Description:
  507. Stores the document data from back to the printer system.
  508. Arguments:
  509. None.
  510. Return Value:
  511. TRUE - Server data stored successfully,
  512. FALSE - if document data was not stored.
  513. --*/
  514. BOOL
  515. TServerData::
  516. bStore(
  517. VOID
  518. )
  519. {
  520. return TRUE;
  521. }
  522. /********************************************************************
  523. Server Property Base Class
  524. ********************************************************************/
  525. /*++
  526. Routine Name:
  527. TServerProp
  528. Routine Description:
  529. Initialized the server property sheet base class
  530. Arguments:
  531. pServerData - Pointer to server data needed for all property sheets.
  532. Return Value:
  533. None.
  534. --*/
  535. TServerProp::
  536. TServerProp(
  537. IN TServerData* pServerData
  538. ) : _pServerData( pServerData )
  539. {
  540. }
  541. /*++
  542. Routine Name:
  543. ~TServerProp
  544. Routine Description:
  545. Base class desctuctor.
  546. Arguments:
  547. None.
  548. Return Value:
  549. Nothing.
  550. --*/
  551. TServerProp::
  552. ~TServerProp(
  553. )
  554. {
  555. }
  556. /*++
  557. Routine Name:
  558. bValid
  559. Routine Description:
  560. Determis if an object is in a valid state.
  561. Arguments:
  562. None.
  563. Return Value:
  564. TRUE object is valid. FALSE object is not valid.
  565. --*/
  566. BOOL
  567. TServerProp::
  568. bValid(
  569. VOID
  570. )
  571. {
  572. return ( _pServerData ) ? TRUE : FALSE;
  573. }
  574. /*++
  575. Routine Name:
  576. vCancelToClose
  577. Routine Description:
  578. Change the cancel button to close, the user has basically
  579. made a change that cannot be undone using the cancel button.
  580. Arguments:
  581. None.
  582. Return Value:
  583. Nothing.
  584. --*/
  585. VOID
  586. TServerProp::
  587. vCancelToClose(
  588. IN HWND hDlg
  589. )
  590. {
  591. PropSheet_CancelToClose( GetParent( hDlg ) );
  592. _pServerData->bCancelButtonIsClose() = TRUE;
  593. }
  594. /*++
  595. Routine Name:
  596. bHandleMessage
  597. Routine Description:
  598. Base class message handler. This routine is called by
  599. derived classes who do not want to handle the message.
  600. Arguments:
  601. uMsg - Windows message
  602. wParam - Word parameter
  603. lParam - Long parameter
  604. Return Value:
  605. TRUE if message was handled, FALSE if message not handled.
  606. --*/
  607. BOOL
  608. TServerProp::
  609. bHandleMessage(
  610. IN UINT uMsg,
  611. IN WPARAM wParam,
  612. IN LPARAM lParam
  613. )
  614. {
  615. BOOL bStatus = TRUE;
  616. UNREFERENCED_PARAMETER( wParam );
  617. switch( uMsg ){
  618. //
  619. // Set the values on the UI.
  620. //
  621. case WM_INITDIALOG:
  622. bStatus = bSetUI();
  623. break;
  624. //
  625. // Handle help and context help.
  626. //
  627. case WM_HELP:
  628. case WM_CONTEXTMENU:
  629. bStatus = PrintUIHelp( uMsg, _hDlg, wParam, lParam );
  630. break;
  631. //
  632. // Save the data.
  633. //
  634. case WM_DESTROY:
  635. bStatus = FALSE;
  636. break;
  637. case WM_NOTIFY:
  638. switch( ((LPNMHDR)lParam)->code )
  639. {
  640. //
  641. // User switched to the next page.
  642. //
  643. case PSN_KILLACTIVE:
  644. bStatus = bReadUI();
  645. vSetDlgMsgResult( !bStatus );
  646. //
  647. // Must return true, to make the property sheet
  648. // control look at the dlg message result.
  649. //
  650. bStatus = TRUE;
  651. break;
  652. //
  653. // User has chosen the close or apply button.
  654. //
  655. case PSN_APPLY:
  656. {
  657. LPPSHNOTIFY pPSHNotify = (LPPSHNOTIFY)lParam;
  658. //
  659. // Save the UI to the system.
  660. //
  661. bStatus = bSaveUI();
  662. //
  663. // If there was a failure then switch to this page.
  664. //
  665. if( !bStatus )
  666. {
  667. //
  668. // Switch to page with the error.
  669. //
  670. PropSheet_SetCurSelByID( GetParent( _hDlg ), uGetPageId() );
  671. }
  672. //
  673. // If the lParam is true the close button was used to
  674. // dismiss the dialog. Let the dialog exit if the close
  675. // button was clicked and one of the dialogs failed.
  676. //
  677. if( pPSHNotify->lParam == TRUE && bStatus == FALSE )
  678. {
  679. //
  680. // If the cancel button is has the closed text, then
  681. // prompt the user if they want to exit on failure.
  682. // The cancel button state is stored in the server data
  683. // because it has to be global to all property sheets.
  684. //
  685. if( _pServerData->bCancelButtonIsClose() )
  686. {
  687. //
  688. // Display the error message.
  689. //
  690. if( iMessage( _hDlg,
  691. IDS_SERVER_PROPERTIES_TITLE,
  692. IDS_ERR_WANT_TO_EXIT,
  693. MB_YESNO|MB_ICONSTOP,
  694. kMsgNone,
  695. NULL ) == IDYES )
  696. {
  697. bStatus = TRUE;
  698. }
  699. }
  700. }
  701. //
  702. // Indicate the return value to the property sheet control
  703. //
  704. vSetDlgMsgResult( bStatus == FALSE ? PSNRET_INVALID_NOCHANGEPAGE : PSNRET_NOERROR );
  705. //
  706. // Must return true, to make the property sheet
  707. // control look at the dlg message result.
  708. //
  709. bStatus = TRUE;
  710. }
  711. break;
  712. //
  713. // Indicate the user chose the cancel button.
  714. //
  715. case PSN_QUERYCANCEL:
  716. bStatus = FALSE;
  717. break;
  718. default:
  719. bStatus = FALSE;
  720. break;
  721. }
  722. break;
  723. default:
  724. bStatus = FALSE;
  725. break;
  726. }
  727. return bStatus;
  728. }
  729. /********************************************************************
  730. Forms Server Property Sheet.
  731. ********************************************************************/
  732. /*++
  733. Routine Name:
  734. TServerForms
  735. Routine Description:
  736. Document property sheet derived class.
  737. Arguments:
  738. None.
  739. Return Value:
  740. Nothing.
  741. --*/
  742. TServerForms::
  743. TServerForms(
  744. IN TServerData *pServerData
  745. ) : TServerProp( pServerData )
  746. {
  747. //
  748. // This does forms specific initialization.
  749. //
  750. _p = FormsInit( pServerData->pszServerName(),
  751. pServerData->hPrintServer(),
  752. pServerData->bAdministrator(),
  753. pServerData->strMachineName() );
  754. }
  755. /*++
  756. Routine Name:
  757. ~TServerForms
  758. Routine Description:
  759. Document derived class destructor.
  760. Arguments:
  761. None.
  762. Return Value:
  763. Nothing.
  764. --*/
  765. TServerForms::
  766. ~TServerForms(
  767. VOID
  768. )
  769. {
  770. //
  771. // Forms specific termination.
  772. //
  773. FormsFini( _p );
  774. }
  775. /*++
  776. Routine Name:
  777. bValid
  778. Routine Description:
  779. Document property sheet derived class valid object indicator.
  780. Arguments:
  781. None.
  782. Return Value:
  783. Returns the status of the base class.
  784. --*/
  785. BOOL
  786. TServerForms::
  787. bValid(
  788. VOID
  789. )
  790. {
  791. return ( _p ) ? TRUE : FALSE;
  792. }
  793. /*++
  794. Routine Name:
  795. bSetUI
  796. Routine Description:
  797. Loads the property sheet dialog with the document data
  798. information.
  799. Arguments:
  800. None.
  801. Return Value:
  802. TRUE if data loaded successfully, FALSE if error occurred.
  803. --*/
  804. BOOL
  805. TServerForms::
  806. bSetUI(
  807. VOID
  808. )
  809. {
  810. return TRUE;
  811. }
  812. /*++
  813. Routine Name:
  814. bReadUI
  815. Routine Description:
  816. Stores the property information to the print server.
  817. Arguments:
  818. Nothing data is contained with in the class.
  819. Return Value:
  820. TRUE if data is stores successfully, FALSE if error occurred.
  821. --*/
  822. BOOL
  823. TServerForms::
  824. bReadUI(
  825. VOID
  826. )
  827. {
  828. return TRUE;
  829. }
  830. /*++
  831. Routine Name:
  832. bSaveUI
  833. Routine Description:
  834. Saves the UI data to some API call or print server.
  835. Arguments:
  836. Nothing data is contained with in the class.
  837. Return Value:
  838. TRUE if data is stores successfully, FALSE if error occurred.
  839. --*/
  840. BOOL
  841. TServerForms::
  842. bSaveUI(
  843. VOID
  844. )
  845. {
  846. // force a save form event.
  847. bHandleMessage( WM_COMMAND,
  848. (WPARAM)MAKELPARAM( IDD_FM_PB_SAVEFORM, kMagic ),
  849. (LPARAM)GetDlgItem( _hDlg, IDD_FM_PB_SAVEFORM ));
  850. // check to see if failed
  851. return (ERROR_SUCCESS == Forms_GetLastError(_p));
  852. }
  853. /*++
  854. Routine Name:
  855. bHandleMessage
  856. Routine Description:
  857. Server property sheet message handler. This handler only
  858. handles events it wants and the base class handle will do the
  859. standard message handling.
  860. Arguments:
  861. uMsg - Windows message
  862. wParam - Word parameter
  863. lParam - Long parameter
  864. Return Value:
  865. TRUE if message was handled, FALSE if message not handled.
  866. --*/
  867. BOOL
  868. TServerForms::
  869. bHandleMessage(
  870. IN UINT uMsg,
  871. IN WPARAM wParam,
  872. IN LPARAM lParam
  873. )
  874. {
  875. BOOL bStatus = FALSE;
  876. LONG_PTR PrevValue;
  877. //
  878. // !!Hack!!
  879. //
  880. // This is code to get the borrowed forms dialog
  881. // code from printman, to work. It is saving our "this" pointer and
  882. // placing the forms specific data in the GWL_USERDATA.
  883. //
  884. PrevValue = GetWindowLongPtr( _hDlg, GWLP_USERDATA );
  885. SetWindowLongPtr( _hDlg, GWLP_USERDATA, (LONG_PTR)_p );
  886. if( uMsg == WM_INITDIALOG )
  887. {
  888. lParam = (LPARAM)_p;
  889. }
  890. bStatus = FormsDlg( _hDlg, uMsg, wParam, lParam );
  891. SetWindowLongPtr( _hDlg, GWLP_USERDATA, PrevValue );
  892. //
  893. // If the message was handled - check to call PSM_CANCELTOCLOSE
  894. //
  895. if( bStatus && Forms_IsThereCommitedChanges(_p) )
  896. {
  897. vCancelToClose( _hDlg );
  898. }
  899. //
  900. // If the message was not handled pass it on to the derrived base class.
  901. //
  902. if( !bStatus )
  903. {
  904. bStatus = TServerProp::bHandleMessage( uMsg, wParam, lParam );
  905. }
  906. return bStatus;
  907. }
  908. /********************************************************************
  909. Settings Server Property Sheet.
  910. ********************************************************************/
  911. /*++
  912. Routine Name:
  913. TServerSettings
  914. Routine Description:
  915. Document property sheet derived class.
  916. Arguments:
  917. None.
  918. Return Value:
  919. Nothing.
  920. --*/
  921. TServerSettings::
  922. TServerSettings(
  923. IN TServerData *pServerData
  924. ) : TServerProp( pServerData ),
  925. _bBeepErrorJobs( FALSE ),
  926. _bEventLogging( FALSE ),
  927. _bNotifyPrintedJobs( FALSE ),
  928. _bNotifyLocalPrintedJobs( FALSE ),
  929. _bNotifyNetworkPrintedJobs( TRUE ),
  930. _bNotifyPrintedJobsComputer( FALSE ),
  931. _bChanged( FALSE ),
  932. _bDownLevelServer( TRUE ),
  933. _bNewOptionSupport( TRUE )
  934. {
  935. }
  936. /*++
  937. Routine Name:
  938. ~TServerSettings
  939. Routine Description:
  940. Document derived class destructor.
  941. Arguments:
  942. None.
  943. Return Value:
  944. Nothing.
  945. --*/
  946. TServerSettings::
  947. ~TServerSettings(
  948. VOID
  949. )
  950. {
  951. }
  952. /*++
  953. Routine Name:
  954. bValid
  955. Routine Description:
  956. Document property sheet derived class valid object indicator.
  957. Arguments:
  958. None.
  959. Return Value:
  960. Returns the status of the base class.
  961. --*/
  962. BOOL
  963. TServerSettings::
  964. bValid(
  965. VOID
  966. )
  967. {
  968. return TServerProp::bValid();
  969. }
  970. /*++
  971. Routine Name:
  972. bSetUI
  973. Routine Description:
  974. Loads the property sheet dialog with the document data
  975. information.
  976. Arguments:
  977. None.
  978. Return Value:
  979. TRUE if data loaded successfully, FALSE if error occurred.
  980. --*/
  981. BOOL
  982. TServerSettings::
  983. bSetUI(
  984. VOID
  985. )
  986. {
  987. return bSetUI( kServerAttributesLoad );
  988. }
  989. /*++
  990. Routine Name:
  991. bSetUI
  992. Routine Description:
  993. Loads the property sheet dialog with the document data
  994. information.
  995. Arguments:
  996. The specified load type.
  997. Return Value:
  998. TRUE if data loaded successfully, FALSE if error occurred.
  999. --*/
  1000. BOOL
  1001. TServerSettings::
  1002. bSetUI(
  1003. INT LoadType
  1004. )
  1005. {
  1006. DBGMSG( DBG_TRACE, ( "TServerSettings::bSetUI\n") );
  1007. //
  1008. // Set the printer title.
  1009. //
  1010. if( !bSetEditText( _hDlg, IDC_SERVER_NAME, _pServerData->strMachineName() ))
  1011. return FALSE;
  1012. //
  1013. // Load the server attributes into the class variables. If this fails
  1014. // it is assumed the machine is either a downlevel server or something
  1015. // went wrong.
  1016. //
  1017. if( sServerAttributes( LoadType ) == kStatusError ){
  1018. //
  1019. // Disable the controls.
  1020. //
  1021. vEnable( FALSE );
  1022. //
  1023. // Indicate the server is not compatible.
  1024. //
  1025. _bDownLevelServer = FALSE;
  1026. //
  1027. // Display the error message.
  1028. //
  1029. iMessage( _hDlg,
  1030. IDS_SERVER_PROPERTIES_TITLE,
  1031. IDS_ERR_SERVER_SETTINGS_NOT_AVAILABLE,
  1032. MB_OK|MB_ICONSTOP,
  1033. kMsgNone,
  1034. NULL );
  1035. return FALSE;
  1036. }
  1037. //
  1038. // Set the spool directory edit control.
  1039. //
  1040. if( !bSetEditText( _hDlg, IDC_SERVER_SPOOL_DIRECTORY, _strSpoolDirectory ))
  1041. {
  1042. return FALSE;
  1043. }
  1044. //
  1045. // Save a copy of the origianl spool directory.
  1046. //
  1047. if( !_strSpoolDirectoryOrig.bUpdate( _strSpoolDirectory ) )
  1048. {
  1049. return FALSE;
  1050. }
  1051. //
  1052. // Reset the changed flag, the message handler sees a edit control
  1053. // change message when we set the spool directory.
  1054. //
  1055. _bChanged = FALSE;
  1056. //
  1057. // Set check box states.
  1058. //
  1059. vSetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_ERROR, _bEventLogging & EVENTLOG_ERROR_TYPE );
  1060. vSetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_WARN, _bEventLogging & EVENTLOG_WARNING_TYPE );
  1061. vSetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_INFO, _bEventLogging & EVENTLOG_INFORMATION_TYPE );
  1062. vSetCheck( _hDlg, IDC_SERVER_REMOTE_JOB_ERRORS, _bBeepErrorJobs );
  1063. vSetCheck( _hDlg, IDC_SERVER_JOB_NOTIFY, _bNotifyPrintedJobs );
  1064. vSetCheck( _hDlg, IDC_SERVER_LOCAL_JOB_NOTIFY, _bNotifyLocalPrintedJobs );
  1065. vSetCheck( _hDlg, IDC_SERVER_NETWORK_JOB_NOTIFY, _bNotifyNetworkPrintedJobs );
  1066. vSetCheck( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER, _bNotifyPrintedJobsComputer );
  1067. //
  1068. // In remote case, we don't show the "notify user" check box and move the lower controls up.
  1069. //
  1070. if( bIsRemote( _pServerData->pszServerName() ) )
  1071. {
  1072. RECT rc;
  1073. RECT rcUpper;
  1074. int deltaY;
  1075. ShowWindow( GetDlgItem( _hDlg, IDC_SERVER_LOCAL_JOB_NOTIFY ), SW_HIDE );
  1076. ShowWindow( GetDlgItem( _hDlg, IDC_SERVER_NETWORK_JOB_NOTIFY ), SW_HIDE );
  1077. GetWindowRect( GetDlgItem( _hDlg, IDC_SERVER_NETWORK_JOB_NOTIFY ), &rc );
  1078. GetWindowRect( GetDlgItem( _hDlg, IDC_SERVER_REMOTE_JOB_ERRORS ), &rcUpper );
  1079. deltaY = rcUpper.bottom - rc.bottom;
  1080. MoveWindowWrap( GetDlgItem( _hDlg, IDC_DOWNLEVEL_LINE ), 0, deltaY );
  1081. MoveWindowWrap( GetDlgItem( _hDlg, IDC_DOWNLEVEL_TEXT ), 0, deltaY );
  1082. MoveWindowWrap( GetDlgItem( _hDlg, IDC_SERVER_JOB_NOTIFY ), 0, deltaY );
  1083. MoveWindowWrap( GetDlgItem( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER ), 0, deltaY );
  1084. }
  1085. //
  1086. // Only NT 5.0 and greater supports the SPLREG_NET_POPUP_TO_COMPUTER
  1087. //
  1088. if( !_bNewOptionSupport )
  1089. {
  1090. ShowWindow( GetDlgItem( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER ), SW_HIDE);
  1091. }
  1092. //
  1093. // Enable of disable the UI based on the administrator state.
  1094. //
  1095. vEnable( _pServerData->bAdministrator() );
  1096. return TRUE;
  1097. }
  1098. VOID
  1099. TServerSettings::
  1100. vEnable(
  1101. BOOL bState
  1102. )
  1103. {
  1104. //
  1105. // Set the UI control state.
  1106. //
  1107. vEnableCtl( _hDlg, IDC_SERVER_EVENT_LOGGING_ERROR, bState );
  1108. vEnableCtl( _hDlg, IDC_SERVER_EVENT_LOGGING_WARN, bState );
  1109. vEnableCtl( _hDlg, IDC_SERVER_EVENT_LOGGING_INFO, bState );
  1110. vEnableCtl( _hDlg, IDC_SPOOL_FOLDER_TEXT, bState );
  1111. vEnableCtl( _hDlg, IDC_SERVER_SPOOL_DIRECTORY, bState );
  1112. vEnableCtl( _hDlg, IDC_SERVER_REMOTE_JOB_ERRORS, bState );
  1113. vEnableCtl( _hDlg, IDC_DOWNLEVEL_TEXT, bState );
  1114. vEnableCtl( _hDlg, IDC_SERVER_JOB_NOTIFY, bState );
  1115. vEnableCtl( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER, bState && _bNotifyPrintedJobs );
  1116. }
  1117. /*++
  1118. Routine Name:
  1119. bReadUI
  1120. Routine Description:
  1121. Read the UI data storing it back to this object.
  1122. Arguments:
  1123. Nothing data is contained with in the class.
  1124. Return Value:
  1125. TRUE if data is read successfully, FALSE if error occurred.
  1126. --*/
  1127. BOOL
  1128. TServerSettings::
  1129. bReadUI(
  1130. VOID
  1131. )
  1132. {
  1133. DBGMSG( DBG_TRACE, ( "TServerSettings::bReadUI\n") );
  1134. TStatusB bStatus;
  1135. //
  1136. // Read the spool directory edit box.
  1137. //
  1138. bStatus DBGCHK = bGetEditText( _hDlg, IDC_SERVER_SPOOL_DIRECTORY, _strSpoolDirectory );
  1139. //
  1140. // Do minor validation on the spool directory.
  1141. //
  1142. if( _strSpoolDirectory.bEmpty() && _bDownLevelServer )
  1143. {
  1144. //
  1145. // Display the error message.
  1146. //
  1147. iMessage( _hDlg,
  1148. IDS_SERVER_PROPERTIES_TITLE,
  1149. IDS_ERR_SERVER_SETTINGS_INVALID_DIR,
  1150. MB_OK|MB_ICONSTOP,
  1151. kMsgNone,
  1152. NULL );
  1153. bStatus DBGNOCHK = FALSE;
  1154. }
  1155. if( bStatus )
  1156. {
  1157. //
  1158. // Read settings check boxes.
  1159. //
  1160. _bEventLogging = bGetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_ERROR ) << 0;
  1161. _bEventLogging |= bGetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_WARN ) << 1;
  1162. _bEventLogging |= bGetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_INFO ) << 2;
  1163. _bBeepErrorJobs = bGetCheck( _hDlg, IDC_SERVER_REMOTE_JOB_ERRORS );
  1164. _bNotifyLocalPrintedJobs = bGetCheck( _hDlg, IDC_SERVER_LOCAL_JOB_NOTIFY );
  1165. _bNotifyNetworkPrintedJobs = bGetCheck( _hDlg, IDC_SERVER_NETWORK_JOB_NOTIFY );
  1166. _bNotifyPrintedJobs = bGetCheck( _hDlg, IDC_SERVER_JOB_NOTIFY );
  1167. _bNotifyPrintedJobsComputer = bGetCheck( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER );
  1168. }
  1169. return bStatus;
  1170. }
  1171. /*++
  1172. Routine Name:
  1173. bSaveUI
  1174. Routine Description:
  1175. Saves the UI data with some API call to the print server.
  1176. Arguments:
  1177. Nothing data is contained with in the class.
  1178. Return Value:
  1179. TRUE if data is stores successfully, FALSE if error occurred.
  1180. --*/
  1181. BOOL
  1182. TServerSettings::
  1183. bSaveUI(
  1184. VOID
  1185. )
  1186. {
  1187. DBGMSG( DBG_TRACE, ( "TServerSettings::bSaveUI\n") );
  1188. BOOL bStatus = TRUE;
  1189. BOOL bErrorShown = FALSE;
  1190. //
  1191. // If data was chagned save the settings.
  1192. //
  1193. if( _bChanged && _bDownLevelServer ) {
  1194. if( lstrcmpi(_strSpoolDirectoryOrig, _strSpoolDirectory) ) {
  1195. //
  1196. // The spooler folder has been changed. Warn the user
  1197. // for potential loose of the current printing jobs.
  1198. //
  1199. INT iResult = iMessage( _hDlg,
  1200. IDS_SERVER_PROPERTIES_TITLE,
  1201. IDS_SERVER_PROPERTIES_CHANGESPOOLFOLDER_WARN,
  1202. MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2,
  1203. kMsgNone,
  1204. NULL );
  1205. if( IDNO == iResult ) {
  1206. //
  1207. // The user did not what to continue, don't close the dialog.
  1208. //
  1209. SetLastError( ERROR_CANCELLED );
  1210. bStatus = FALSE;
  1211. }
  1212. }
  1213. if( bStatus ) {
  1214. switch( sServerAttributes( kServerAttributesStore ) ){
  1215. case kStatusCannotSaveUserNotification:
  1216. //
  1217. // Display the error message.
  1218. //
  1219. iMessage( _hDlg,
  1220. IDS_SERVER_PROPERTIES_TITLE,
  1221. IDS_ERR_GENERIC,
  1222. MB_OK|MB_ICONHAND,
  1223. kMsgNone,
  1224. NULL );
  1225. bStatus = FALSE;
  1226. bErrorShown = TRUE;
  1227. break;
  1228. case kStatusInvalidSpoolDirectory:
  1229. //
  1230. // Display the error message.
  1231. //
  1232. iMessage( _hDlg,
  1233. IDS_SERVER_PROPERTIES_TITLE,
  1234. IDS_ERR_SERVER_SETTINGS_INVALID_DIR,
  1235. MB_OK|MB_ICONSTOP,
  1236. kMsgNone,
  1237. NULL );
  1238. //
  1239. // Set focus to control with error.
  1240. //
  1241. SetFocus( GetDlgItem( _hDlg, IDC_SERVER_SPOOL_DIRECTORY ) );
  1242. bStatus = FALSE;
  1243. bErrorShown = TRUE;
  1244. break;
  1245. case kStatusSuccess:
  1246. _bChanged = FALSE;
  1247. bStatus = TRUE;
  1248. break;
  1249. case kStatusError:
  1250. default:
  1251. bStatus = FALSE;
  1252. break;
  1253. }
  1254. if( bStatus && _pServerData->bAdministrator() ) {
  1255. //
  1256. // Update the new original spooler directory
  1257. //
  1258. bStatus = _strSpoolDirectoryOrig.bUpdate( _strSpoolDirectory );
  1259. }
  1260. }
  1261. }
  1262. if( !bStatus ) {
  1263. //
  1264. // Display the error message.
  1265. //
  1266. if( GetLastError() != ERROR_CANCELLED && !bErrorShown ) {
  1267. iMessage( _hDlg,
  1268. IDS_SERVER_PROPERTIES_TITLE,
  1269. IDS_ERR_SERVER_SETTINGS_SAVE,
  1270. MB_OK|MB_ICONSTOP,
  1271. kMsgGetLastError,
  1272. NULL );
  1273. }
  1274. }
  1275. return bStatus;
  1276. }
  1277. /*++
  1278. Routine Name:
  1279. sServerAttributes
  1280. Routine Description:
  1281. Loads and stores server attributes.
  1282. Arguments:
  1283. Direction flag either kStore or kLoad pr kDefault
  1284. Return Value:
  1285. Status values, see EStatus for for details.
  1286. --*/
  1287. INT
  1288. TServerSettings::
  1289. sServerAttributes(
  1290. INT iFlag
  1291. )
  1292. {
  1293. INT iStatus;
  1294. TStatusH hr;
  1295. //
  1296. // Create the printer data access class.
  1297. //
  1298. TPrinterDataAccess Data( _pServerData->_hPrintServer );
  1299. TPersist NotifyUser( gszPrinterPositions, TPersist::kCreate|TPersist::kRead|TPersist::kWrite );
  1300. //
  1301. // Relax the return type checking, BOOL are not REG_DWORD but REG_BINARY
  1302. //
  1303. Data.RelaxReturnTypeCheck( TRUE );
  1304. switch( iFlag )
  1305. {
  1306. //
  1307. // Load from the spooler
  1308. //
  1309. case kServerAttributesLoad:
  1310. hr DBGCHK = Data.Get( SPLREG_DEFAULT_SPOOL_DIRECTORY, _strSpoolDirectory );
  1311. hr DBGCHK = Data.Get( SPLREG_BEEP_ENABLED, _bBeepErrorJobs );
  1312. hr DBGCHK = Data.Get( SPLREG_EVENT_LOG, _bEventLogging );
  1313. hr DBGCHK = Data.Get( SPLREG_NET_POPUP, _bNotifyPrintedJobs );
  1314. hr DBGCHK = NotifyUser.bRead( gszLocalPrintNotification, _bNotifyLocalPrintedJobs ) ? S_OK : E_FAIL;
  1315. hr DBGCHK = NotifyUser.bRead( gszNetworkPrintNotification, _bNotifyNetworkPrintedJobs ) ? S_OK : E_FAIL;
  1316. hr DBGCHK = Data.Get( SPLREG_NET_POPUP_TO_COMPUTER, _bNotifyPrintedJobsComputer );
  1317. //
  1318. // If we fail reading the net popup to computer with invalid parameter
  1319. // we are talking to a downlevel machine pre nt 5.0 machine. If this
  1320. // is the case we simple do not show this option in the UI and continue
  1321. // normally.
  1322. //
  1323. if( FAILED( hr ) && HRESULT_CODE( hr ) == ERROR_INVALID_PARAMETER )
  1324. {
  1325. _bNewOptionSupport = FALSE;
  1326. }
  1327. //
  1328. // If were are talking to a downlevel machine pre nt 4.0,
  1329. // get printer data calls will fail with error invalid handle. We
  1330. // only check the last value read, since this error code should never
  1331. // happen on any calls to get printer data.
  1332. //
  1333. if( FAILED( hr ) && HRESULT_CODE( hr ) == ERROR_INVALID_HANDLE )
  1334. {
  1335. iStatus = kStatusError;
  1336. }
  1337. else
  1338. {
  1339. iStatus = kStatusSuccess;
  1340. }
  1341. break;
  1342. //
  1343. // Store to the spooler
  1344. //
  1345. case kServerAttributesStore:
  1346. //
  1347. // We save this data for local case
  1348. //
  1349. if( !bIsRemote( _pServerData->pszServerName() ) && VALID_OBJ( NotifyUser ) )
  1350. {
  1351. if( !NotifyUser.bWrite( gszLocalPrintNotification, _bNotifyLocalPrintedJobs ) ||
  1352. !NotifyUser.bWrite( gszNetworkPrintNotification, _bNotifyNetworkPrintedJobs ) )
  1353. {
  1354. iStatus = kStatusCannotSaveUserNotification;
  1355. break;
  1356. }
  1357. }
  1358. //
  1359. // If the current user is not administrator, we just return
  1360. //
  1361. if( !_pServerData->bAdministrator() )
  1362. {
  1363. iStatus = kStatusSuccess;
  1364. break;
  1365. }
  1366. hr DBGCHK = Data.Set( SPLREG_DEFAULT_SPOOL_DIRECTORY, _strSpoolDirectory );
  1367. if( FAILED( hr ) )
  1368. {
  1369. iStatus = kStatusInvalidSpoolDirectory;
  1370. }
  1371. else
  1372. {
  1373. if( SUCCEEDED( hr ) )
  1374. {
  1375. hr DBGCHK = Data.Set( SPLREG_BEEP_ENABLED, _bBeepErrorJobs );
  1376. }
  1377. if( SUCCEEDED( hr ) )
  1378. {
  1379. hr DBGCHK = Data.Set( SPLREG_EVENT_LOG, _bEventLogging );
  1380. }
  1381. if( SUCCEEDED( hr ) )
  1382. {
  1383. hr DBGCHK = Data.Set( SPLREG_NET_POPUP, _bNotifyPrintedJobs );
  1384. }
  1385. if( SUCCEEDED( hr ) && _bNewOptionSupport )
  1386. {
  1387. hr DBGCHK = Data.Set( SPLREG_NET_POPUP_TO_COMPUTER, _bNotifyPrintedJobsComputer );
  1388. }
  1389. if( SUCCEEDED( hr ) )
  1390. {
  1391. iStatus = kStatusSuccess;
  1392. if( HRESULT_CODE( hr ) == ERROR_SUCCESS_RESTART_REQUIRED )
  1393. {
  1394. _pServerData->_bRebootRequired = TRUE;
  1395. }
  1396. }
  1397. else
  1398. {
  1399. iStatus = kStatusError;
  1400. }
  1401. }
  1402. break;
  1403. //
  1404. // Load defaults from the spooler.
  1405. //
  1406. case kServerAttributesDefault:
  1407. iStatus = kStatusSuccess;
  1408. break;
  1409. //
  1410. // Default is to return an error.
  1411. //
  1412. default:
  1413. iStatus = kStatusError;
  1414. break;
  1415. }
  1416. return iStatus;
  1417. }
  1418. /*++
  1419. Routine Name:
  1420. bHandleMessage
  1421. Routine Description:
  1422. Server property sheet message handler. This handler only
  1423. handles events it wants and the base class handle will do the
  1424. standard message handling.
  1425. Arguments:
  1426. uMsg - Windows message
  1427. wParam - Word parameter
  1428. lParam - Long parameter
  1429. Return Value:
  1430. TRUE if message was handled, FALSE if message not handled.
  1431. --*/
  1432. BOOL
  1433. TServerSettings::
  1434. bHandleMessage(
  1435. IN UINT uMsg,
  1436. IN WPARAM wParam,
  1437. IN LPARAM lParam
  1438. )
  1439. {
  1440. BOOL bStatus = FALSE;
  1441. BOOL bChanged = FALSE;
  1442. switch( uMsg ){
  1443. case WM_COMMAND:
  1444. //
  1445. // Monitor changes in the UI to highlight the apply button.
  1446. //
  1447. switch( GET_WM_COMMAND_ID( wParam, lParam ) ) {
  1448. case IDC_SERVER_SPOOL_DIRECTORY:
  1449. bChanged = GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE;
  1450. bStatus = TRUE;
  1451. break;
  1452. case IDC_SERVER_REMOTE_JOB_ERRORS:
  1453. case IDC_SERVER_LOCAL_JOB_NOTIFY:
  1454. case IDC_SERVER_NETWORK_JOB_NOTIFY:
  1455. case IDC_SERVER_JOB_NOTIFY:
  1456. case IDC_SERVER_JOB_NOTIFY_COMPUTER:
  1457. case IDC_SERVER_EVENT_LOGGING_ERROR:
  1458. case IDC_SERVER_EVENT_LOGGING_WARN:
  1459. case IDC_SERVER_EVENT_LOGGING_INFO:
  1460. {
  1461. if( IDC_SERVER_JOB_NOTIFY == GET_WM_COMMAND_ID( wParam, lParam ) )
  1462. {
  1463. vEnableCtl( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER,
  1464. bGetCheck( _hDlg, IDC_SERVER_JOB_NOTIFY ) );
  1465. }
  1466. bChanged = TRUE;
  1467. bStatus = TRUE;
  1468. }
  1469. break;
  1470. default:
  1471. bStatus = FALSE;
  1472. break;
  1473. }
  1474. break;
  1475. default:
  1476. bStatus = FALSE;
  1477. break;
  1478. }
  1479. //
  1480. // If something changed enable the apply button.
  1481. //
  1482. if( bChanged ){
  1483. _bChanged = TRUE;
  1484. PropSheet_Changed( GetParent( _hDlg ), _hDlg );
  1485. }
  1486. //
  1487. // If the message was not handled let the base class handle it.
  1488. //
  1489. if( bStatus == FALSE )
  1490. bStatus = TServerProp::bHandleMessage( uMsg, wParam, lParam );
  1491. return bStatus;
  1492. }
  1493. /********************************************************************
  1494. Port selection.
  1495. ********************************************************************/
  1496. TServerPorts::
  1497. TServerPorts(
  1498. IN TServerData *pServerData
  1499. ) : TServerProp( pServerData )
  1500. {
  1501. }
  1502. TServerPorts::
  1503. ~TServerPorts(
  1504. VOID
  1505. )
  1506. {
  1507. }
  1508. BOOL
  1509. TServerPorts::
  1510. bValid(
  1511. VOID
  1512. )
  1513. {
  1514. return ( TServerProp::bValid() && _PortsLV.bValid() );
  1515. }
  1516. BOOL
  1517. TServerPorts::
  1518. bReadUI(
  1519. VOID
  1520. )
  1521. {
  1522. return TRUE;
  1523. }
  1524. BOOL
  1525. TServerPorts::
  1526. bSaveUI(
  1527. VOID
  1528. )
  1529. {
  1530. return TRUE;
  1531. }
  1532. /*++
  1533. Routine Name:
  1534. bSetUI
  1535. Routine Description:
  1536. Loads the property sheet dialog with the document data
  1537. information.
  1538. Arguments:
  1539. None.
  1540. Return Value:
  1541. TRUE if data loaded successfully, FALSE if error occurred.
  1542. --*/
  1543. BOOL
  1544. TServerPorts::
  1545. bSetUI(
  1546. VOID
  1547. )
  1548. {
  1549. //
  1550. // Set the printer title.
  1551. //
  1552. if( !bSetEditText( _hDlg, IDC_SERVER_NAME, _pServerData->strMachineName() ))
  1553. {
  1554. vShowUnexpectedError( _pServerData->hwnd(), IDS_SERVER_PROPERTIES_TITLE );
  1555. return FALSE;
  1556. }
  1557. //
  1558. // Initialize the ports listview.
  1559. //
  1560. if( !_PortsLV.bSetUI( GetDlgItem( _hDlg, IDC_PORTS ), FALSE, FALSE, TRUE, _hDlg, 0, 0, IDC_PORT_DELETE ) )
  1561. {
  1562. DBGMSG( DBG_WARN, ( "ServerPort.vSetUI: failed %d\n", GetLastError( )));
  1563. vShowUnexpectedError( _pServerData->hwnd(), IDS_SERVER_PROPERTIES_TITLE );
  1564. return FALSE;
  1565. }
  1566. //
  1567. // Load ports into the view.
  1568. //
  1569. if( !_PortsLV.bReloadPorts( _pServerData->pszServerName() ) )
  1570. {
  1571. DBGMSG( DBG_WARN, ( "ServerPort.vSetUI: bReloadPorts failed %d\n", GetLastError( )));
  1572. vShowUnexpectedError( _pServerData->hwnd(), IDS_SERVER_PROPERTIES_TITLE );
  1573. return FALSE;
  1574. }
  1575. //
  1576. // Select the first item
  1577. //
  1578. _PortsLV.vSelectItem( 0 );
  1579. //
  1580. // Adding / deleting / configuring ports is not supported on remote downlevel machines.
  1581. //
  1582. if( !_pServerData->bAdministrator() || _pServerData->bRemoteDownLevel() )
  1583. {
  1584. //
  1585. // Disable things if not administrator.
  1586. //
  1587. vEnableCtl( _hDlg, IDC_PORT_CREATE, FALSE );
  1588. vEnableCtl( _hDlg, IDC_PORT_DELETE, FALSE );
  1589. vEnableCtl( _hDlg, IDC_PROPERTIES, FALSE );
  1590. }
  1591. //
  1592. // Bidi support is currently disabled.
  1593. //
  1594. ShowWindow( GetDlgItem( _hDlg, IDC_ENABLE_BIDI ), SW_HIDE );
  1595. return TRUE;
  1596. }
  1597. /*++
  1598. Routine Name:
  1599. bHandleMessage
  1600. Routine Description:
  1601. Server property sheet message handler. This handler only
  1602. handles events it wants and the base class handle will do the
  1603. standard message handling.
  1604. Arguments:
  1605. uMsg - Windows message
  1606. wParam - Word parameter
  1607. lParam - Long parameter
  1608. Return Value:
  1609. TRUE if message was handled, FALSE if message not handled.
  1610. --*/
  1611. BOOL
  1612. TServerPorts::
  1613. bHandleMessage(
  1614. UINT uMsg,
  1615. WPARAM wParam,
  1616. LPARAM lParam
  1617. )
  1618. {
  1619. BOOL bStatus = FALSE;
  1620. switch( uMsg ){
  1621. case WM_COMMAND:
  1622. switch( GET_WM_COMMAND_ID( wParam, lParam ) ){
  1623. case IDC_PORT_DELETE:
  1624. {
  1625. //
  1626. // Delete the selected port.
  1627. //
  1628. HWND hwnd = GetDlgItem( _hDlg, IDC_PORT_DELETE );
  1629. //
  1630. // We will only delete the port if the button is enabled, this check is
  1631. // necessary if the user uses the delete key on the keyboard to delete
  1632. // the port.
  1633. //
  1634. if( IsWindowEnabled( hwnd ) )
  1635. {
  1636. bStatus = _PortsLV.bDeletePorts( _hDlg, _pServerData->pszServerName( ));
  1637. if( bStatus )
  1638. {
  1639. SetFocus( hwnd );
  1640. }
  1641. }
  1642. }
  1643. break;
  1644. case IDC_PROPERTIES:
  1645. //
  1646. // Configure the selected port.
  1647. //
  1648. bStatus = _PortsLV.bConfigurePort( _hDlg, _pServerData->pszServerName( ));
  1649. SetFocus( GetDlgItem( _hDlg, IDC_PROPERTIES ) );
  1650. break;
  1651. case IDC_PORT_CREATE: {
  1652. //
  1653. // Create add ports class.
  1654. //
  1655. TAddPort AddPort( _hDlg,
  1656. _pServerData->pszServerName(),
  1657. TRUE );
  1658. //
  1659. // Insure the add port was created successfully.
  1660. //
  1661. bStatus = VALID_OBJ( AddPort );
  1662. if( !bStatus ) {
  1663. vShowUnexpectedError( _hDlg, TAddPort::kErrorMessage );
  1664. } else {
  1665. //
  1666. // Interact with the Add Ports dialog.
  1667. //
  1668. bStatus = AddPort.bDoModal();
  1669. if( bStatus ){
  1670. //
  1671. // Load the machine's ports into the listview.
  1672. //
  1673. bStatus = _PortsLV.bReloadPorts( _pServerData->pszServerName( ), TRUE );
  1674. }
  1675. }
  1676. }
  1677. break;
  1678. default:
  1679. bStatus = FALSE;
  1680. break;
  1681. }
  1682. break;
  1683. case WM_NOTIFY:
  1684. //
  1685. // Handle any ports list view messages.
  1686. //
  1687. switch( wParam )
  1688. {
  1689. case IDC_PORTS:
  1690. //
  1691. // Enable/disable buttons depending on the current status
  1692. //
  1693. if( _pServerData->bAdministrator() && ( ((LPNMHDR)lParam)->code == LVN_ITEMCHANGED ) )
  1694. {
  1695. if( _pServerData->bRemoteDownLevel() )
  1696. {
  1697. // remote or downlevel case - all buttons will be disabled
  1698. vEnableCtl( _hDlg, IDC_PORT_CREATE, FALSE );
  1699. vEnableCtl( _hDlg, IDC_PORT_DELETE, FALSE );
  1700. vEnableCtl( _hDlg, IDC_PROPERTIES, FALSE );
  1701. }
  1702. else if( 0 == _PortsLV.cSelectedItems() )
  1703. {
  1704. // no selection case. disable config & delete buttons
  1705. vEnableCtl( _hDlg, IDC_PORT_CREATE, TRUE );
  1706. vEnableCtl( _hDlg, IDC_PORT_DELETE, FALSE );
  1707. vEnableCtl( _hDlg, IDC_PROPERTIES, FALSE );
  1708. }
  1709. else if( 1 == _PortsLV.cSelectedItems() )
  1710. {
  1711. // only one port is selected - enable all buttons
  1712. vEnableCtl( _hDlg, IDC_PORT_CREATE, TRUE );
  1713. vEnableCtl( _hDlg, IDC_PORT_DELETE, TRUE );
  1714. vEnableCtl( _hDlg, IDC_PROPERTIES, TRUE );
  1715. }
  1716. else
  1717. {
  1718. // many ports are selected and we are not in remote and/or downlevel case
  1719. // enable only the create and delete buttons
  1720. vEnableCtl( _hDlg, IDC_PORT_CREATE, TRUE );
  1721. vEnableCtl( _hDlg, IDC_PORT_DELETE, TRUE );
  1722. vEnableCtl( _hDlg, IDC_PROPERTIES, FALSE );
  1723. }
  1724. }
  1725. (VOID)_PortsLV.bHandleNotifyMessage( lParam );
  1726. bStatus = FALSE;
  1727. break;
  1728. default:
  1729. bStatus = FALSE;
  1730. break;
  1731. }
  1732. break;
  1733. default:
  1734. bStatus = FALSE;
  1735. break;
  1736. }
  1737. //
  1738. // If the message was handled.
  1739. //
  1740. if( bStatus != FALSE )
  1741. {
  1742. vCancelToClose( _hDlg );
  1743. return bStatus;
  1744. }
  1745. //
  1746. // If the message was not handled pass it on to the base class.
  1747. //
  1748. if( bStatus == FALSE )
  1749. bStatus = TServerProp::bHandleMessage( uMsg, wParam, lParam );
  1750. return bStatus;
  1751. }
  1752. /********************************************************************
  1753. Server Driver Administration.
  1754. ********************************************************************/
  1755. TServerDrivers::
  1756. TServerDrivers(
  1757. IN TServerData *pServerData
  1758. ) : TServerProp( pServerData ),
  1759. _bChanged( FALSE ),
  1760. _bCanRemoveDrivers( TRUE )
  1761. {
  1762. }
  1763. TServerDrivers::
  1764. ~TServerDrivers(
  1765. VOID
  1766. )
  1767. {
  1768. }
  1769. BOOL
  1770. TServerDrivers::
  1771. bValid(
  1772. VOID
  1773. )
  1774. {
  1775. return TServerProp::bValid() && VALID_OBJ( _DriversLV );
  1776. }
  1777. BOOL
  1778. TServerDrivers::
  1779. bReadUI(
  1780. VOID
  1781. )
  1782. {
  1783. return TRUE;
  1784. }
  1785. /*++
  1786. Routine Name:
  1787. bSaveUI
  1788. Routine Description:
  1789. Save the contenst of the UI to the system.
  1790. Arguments:
  1791. None.
  1792. Return Value:
  1793. TRUE if save was successful, FALSE if error occurred.
  1794. --*/
  1795. BOOL
  1796. TServerDrivers::
  1797. bSaveUI(
  1798. VOID
  1799. )
  1800. {
  1801. //
  1802. // Display the hour glass the refresh may take awhile.
  1803. //
  1804. TWaitCursor Cur;
  1805. //
  1806. // Create a driver noitfy.
  1807. //
  1808. TServerDriverNotify Notify ( this );
  1809. //
  1810. // Install / Remove / Update any drivers.
  1811. //
  1812. (VOID)_DriversLV.bSendDriverInfoNotification( Notify );
  1813. //
  1814. // Refesh the drivers list.
  1815. //
  1816. TStatusB bStatus;
  1817. bStatus DBGCHK = _DriversLV.bRefresh();
  1818. if( !bStatus )
  1819. {
  1820. //
  1821. // Display the error message.
  1822. //
  1823. iMessage( _hDlg,
  1824. IDS_SERVER_PROPERTIES_TITLE,
  1825. IDS_ERR_DRIVERS_NOT_REFRESHED,
  1826. MB_OK|MB_ICONSTOP,
  1827. kMsgGetLastError,
  1828. NULL );
  1829. }
  1830. //
  1831. // Sort the environment column.
  1832. //
  1833. (VOID)_DriversLV.bSortColumn( TDriversLV::kEnvironmentColumn );
  1834. //
  1835. // Sort the driver name.
  1836. //
  1837. (VOID)_DriversLV.bSortColumn( TDriversLV::kDriverNameColumn );
  1838. //
  1839. // Select the first item in the list view.
  1840. //
  1841. _DriversLV.vSelectItem( 0 );
  1842. //
  1843. // Return success only if there was not a falure and the refresh succeeded.
  1844. //
  1845. return bStatus;
  1846. }
  1847. /*++
  1848. Routine Name:
  1849. bSetUI
  1850. Routine Description:
  1851. Loads the property sheet dialog with the document data
  1852. information.
  1853. Arguments:
  1854. None.
  1855. Return Value:
  1856. TRUE if data loaded successfully, FALSE if error occurred.
  1857. --*/
  1858. BOOL
  1859. TServerDrivers::
  1860. bSetUI(
  1861. VOID
  1862. )
  1863. {
  1864. TStatusB bStatus;
  1865. //
  1866. // Set the printer title.
  1867. //
  1868. bStatus DBGCHK = bSetEditText( _hDlg, IDC_SERVER_NAME, _pServerData->strMachineName() );
  1869. //
  1870. // If we are an administrator handle the delete message.
  1871. //
  1872. UINT idRemove = _pServerData->bAdministrator() ? IDC_REMOVE_DRIVER : 0;
  1873. //
  1874. // Set the drivers list view.
  1875. //
  1876. bStatus DBGCHK = _DriversLV.bSetUI( _pServerData->pszServerName(), _hDlg, IDC_MORE_DETAILS, IDC_ITEM_SELECTED, idRemove );
  1877. //
  1878. // Load the list view with driver data.
  1879. //
  1880. bStatus DBGCHK = _DriversLV.bRefresh();
  1881. //
  1882. // Set the default sort order.
  1883. //
  1884. bStatus DBGCHK = _DriversLV.bSortColumn( TDriversLV::kEnvironmentColumn );
  1885. //
  1886. // Sort the driver name.
  1887. //
  1888. bStatus DBGCHK = _DriversLV.bSortColumn( TDriversLV::kDriverNameColumn );
  1889. //
  1890. // Update the button state.
  1891. //
  1892. vUpdateButtons();
  1893. //
  1894. // Select the first item in the list view.
  1895. //
  1896. _DriversLV.vSelectItem( 0 );
  1897. //
  1898. // If we are talking to a down level spooler then deleting printer drivers
  1899. // can only be done with a call to DeletePrinterDriver, no ex version exists.
  1900. // Because DeletePrinterDriver only allows the caller to delete all drivers
  1901. // of a specific environment with out regards to version, we have decided to
  1902. // not allow removing printer drivers on down level machines. In addition
  1903. // DeletePrinterDriver is as kind of broken since it does not actually remove
  1904. // the driver files, it only removes the registry entries.
  1905. //
  1906. if( GetDriverVersion( _pServerData->dwDriverVersion() ) <= 2 )
  1907. {
  1908. _bCanRemoveDrivers = FALSE;
  1909. }
  1910. return bStatus;
  1911. }
  1912. /*++
  1913. Routine Name:
  1914. vUpdateButtons
  1915. Routine Description:
  1916. Update the dialog buttons.
  1917. Arguments:
  1918. None.
  1919. Return Value:
  1920. Nothing.
  1921. --*/
  1922. VOID
  1923. TServerDrivers::
  1924. vUpdateButtons(
  1925. VOID
  1926. )
  1927. {
  1928. //
  1929. // Default is the details button disabled.
  1930. //
  1931. vEnableCtl( _hDlg, IDC_MORE_DETAILS, FALSE );
  1932. vEnableCtl( _hDlg, IDC_UPDATE_DRIVER, FALSE );
  1933. vEnableCtl( _hDlg, IDC_REMOVE_DRIVER, FALSE );
  1934. //
  1935. // If not an administrator then disable the add button.
  1936. //
  1937. if( !_pServerData->bAdministrator() )
  1938. {
  1939. vEnableCtl( _hDlg, IDC_ADD_DRIVER, FALSE );
  1940. }
  1941. }
  1942. /*++
  1943. Routine Name:
  1944. bHandleMessage
  1945. Routine Description:
  1946. Server property sheet message handler. This handler only
  1947. handles events it wants and the base class handle will do the
  1948. standard message handling.
  1949. Arguments:
  1950. uMsg - Windows message
  1951. wParam - Word parameter
  1952. lParam - Long parameter
  1953. Return Value:
  1954. TRUE if message was handled, FALSE if message not handled.
  1955. --*/
  1956. BOOL
  1957. TServerDrivers::
  1958. bHandleMessage(
  1959. UINT uMsg,
  1960. WPARAM wParam,
  1961. LPARAM lParam
  1962. )
  1963. {
  1964. BOOL bStatus = TRUE;
  1965. BOOL bChanged = FALSE;
  1966. switch( uMsg )
  1967. {
  1968. case WM_COMMAND:
  1969. switch( GET_WM_COMMAND_ID( wParam, lParam ) )
  1970. {
  1971. case IDC_ADD_DRIVER:
  1972. if( bHandleAddDriver( uMsg, wParam, lParam ) )
  1973. bChanged = TRUE;
  1974. break;
  1975. case IDC_UPDATE_DRIVER:
  1976. if( bHandleUpdateDriver( uMsg, wParam, lParam ) )
  1977. bChanged = TRUE;
  1978. break;
  1979. case IDC_REMOVE_DRIVER:
  1980. if( bHandleRemoveDriver( uMsg, wParam, lParam ) )
  1981. bChanged = TRUE;
  1982. break;
  1983. case IDC_MORE_DETAILS:
  1984. bHandleDriverDetails( uMsg, wParam, lParam );
  1985. break;
  1986. case IDC_ITEM_SELECTED:
  1987. bHandleDriverItemSelection( uMsg, wParam, lParam );
  1988. break;
  1989. default:
  1990. bStatus = FALSE;
  1991. break;
  1992. }
  1993. break;
  1994. default:
  1995. bStatus = FALSE;
  1996. break;
  1997. }
  1998. //
  1999. // If something changed save the changes and change the
  2000. // the ok button to close and gray the cancel button.
  2001. //
  2002. if( bChanged ){
  2003. //
  2004. // Update the button state.
  2005. //
  2006. vUpdateButtons();
  2007. //
  2008. // Save the UI and convert CancelToClose
  2009. //
  2010. (VOID)bSaveUI();
  2011. vCancelToClose( _hDlg );
  2012. }
  2013. //
  2014. // Let the list view handle their message.
  2015. //
  2016. if( bStatus == FALSE )
  2017. bStatus = _DriversLV.bHandleMessage( uMsg, wParam, lParam );
  2018. //
  2019. // If the message was not handled pass it on to the base class.
  2020. //
  2021. if( bStatus == FALSE )
  2022. bStatus = TServerProp::bHandleMessage( uMsg, wParam, lParam );
  2023. return bStatus;
  2024. }
  2025. BOOL
  2026. TServerDrivers::
  2027. bHandleDriverItemSelection(
  2028. UINT uMsg,
  2029. WPARAM wParam,
  2030. LPARAM lParam
  2031. )
  2032. {
  2033. DBGMSG( DBG_TRACE, ( "TServerDrivers::bHandleDriverItemSelection\n" ) );
  2034. //
  2035. // Get the button state in a local variable.
  2036. //
  2037. BOOL bButtonState = _DriversLV.bIsAnyItemSelcted();
  2038. //
  2039. // If any item is selected then enable the properties button.
  2040. //
  2041. vEnableCtl( _hDlg, IDC_MORE_DETAILS, bButtonState );
  2042. vEnableCtl( _hDlg, IDC_UPDATE_DRIVER, bButtonState && _pServerData->bAdministrator() );
  2043. vEnableCtl( _hDlg, IDC_REMOVE_DRIVER, bButtonState && _pServerData->bAdministrator() && _bCanRemoveDrivers );
  2044. return TRUE;
  2045. }
  2046. BOOL
  2047. TServerDrivers::
  2048. bHandleAddDriver(
  2049. UINT uMsg,
  2050. WPARAM wParam,
  2051. LPARAM lParam
  2052. )
  2053. {
  2054. DBGMSG( DBG_TRACE, ( "TServerDrivers::bHandleAddDriver\n" ) );
  2055. TString strDriverName;
  2056. TStatusB bStatus;
  2057. BOOL bCanceled;
  2058. UINT nDriverInstallCount = 0;
  2059. //
  2060. // Add any new drivers, displaying the add driver wizard.
  2061. //
  2062. bStatus DBGCHK = bInstallNewPrinterDriver( _hDlg,
  2063. TWizard::kDriverInstall,
  2064. _pServerData->pszServerName(),
  2065. strDriverName,
  2066. NULL,
  2067. kDriverWizardDefault,
  2068. &bCanceled,
  2069. FALSE,
  2070. &nDriverInstallCount );
  2071. //
  2072. // If any driver was installed then return true
  2073. // inorder to indicate we need to refresh the driver list view.
  2074. //
  2075. if( nDriverInstallCount )
  2076. {
  2077. bStatus DBGNOCHK = TRUE;
  2078. }
  2079. return bStatus;
  2080. }
  2081. BOOL
  2082. TServerDrivers::
  2083. bHandleRemoveDriver(
  2084. UINT uMsg,
  2085. WPARAM wParam,
  2086. LPARAM lParam
  2087. )
  2088. {
  2089. DBGMSG( DBG_TRACE, ( "TServerDrivers::bHandleRemoveDriver\n" ) );
  2090. //
  2091. // If we cannot remove the drivers because we are administrating
  2092. // a downlevel machine then do nothing.
  2093. //
  2094. if( !_bCanRemoveDrivers )
  2095. {
  2096. return FALSE;
  2097. }
  2098. TStatusB bStatus;
  2099. //
  2100. // Get a list of the selected items.
  2101. //
  2102. UINT nCount = 0;
  2103. TDriverTransfer DriverTransfer;
  2104. bStatus DBGCHK = _DriversLV.bGetSelectedDriverInfo( DriverTransfer, &nCount );
  2105. DBGMSG( DBG_TRACE, ( "Selected count %d\n", nCount ) );
  2106. //
  2107. // Warn the user that they are about to delete a driver
  2108. // from the system permently.
  2109. //
  2110. if( bStatus && nCount )
  2111. {
  2112. bStatus DBGNOCHK = bWarnUserDriverDeletion( DriverTransfer.DriverInfoList_pGetByIndex( 0 ), nCount );
  2113. }
  2114. //
  2115. // Delete the driver if the count is non zero.
  2116. //
  2117. if( bStatus && nCount )
  2118. {
  2119. //
  2120. // Initialize the list iterator.
  2121. //
  2122. TIter Iter;
  2123. DriverTransfer.DriverInfoList_vIterInit( Iter );
  2124. TDriverInfo *pDriverInfo;
  2125. for( Iter.vNext(); Iter.bValid(); )
  2126. {
  2127. pDriverInfo = DriverTransfer.DriverInfoList_pConvert( Iter );
  2128. Iter.vNext();
  2129. DBGMSG( DBG_TRACE, ( "Selected Driver Name: "TSTR"\n", (LPCTSTR)pDriverInfo->strName() ) );
  2130. //
  2131. // If the driver was added but not installed then
  2132. // removed it the item entirely.
  2133. //
  2134. if( pDriverInfo->vGetInfoState() == TDriverInfo::kAdd )
  2135. {
  2136. DBGMSG( DBG_TRACE, ( "Uninstalled driver was removed.\n" ) );
  2137. pDriverInfo->vSetInfoState( TDriverInfo::kRemoved );
  2138. }
  2139. //
  2140. // Mark the item to be removed.
  2141. //
  2142. else
  2143. {
  2144. DBGMSG( DBG_TRACE, ( "Driver removed.\n" ) );
  2145. pDriverInfo->vSetInfoState( TDriverInfo::kRemove );
  2146. }
  2147. }
  2148. //
  2149. // Return the removed items back to the list and delete
  2150. // these items form the UI part of the list view.
  2151. //
  2152. _DriversLV.vDeleteDriverInfoFromListView( DriverTransfer );
  2153. }
  2154. else
  2155. {
  2156. //
  2157. // Return the selected items back to the list view.
  2158. //
  2159. _DriversLV.vReturnDriverInfoToListView( DriverTransfer );
  2160. }
  2161. //
  2162. // If there are no more drivers in the list view then remove
  2163. // default button state from the remove button and change it
  2164. // to the add button, since the add button is always enabled.
  2165. //
  2166. if( !_DriversLV.uGetListViewItemCount() )
  2167. {
  2168. SendMessage( GetDlgItem( _hDlg, IDC_REMOVE_DRIVER ),
  2169. BM_SETSTYLE,
  2170. MAKEWPARAM( BS_PUSHBUTTON, 0 ),
  2171. MAKELPARAM( TRUE, 0 ) );
  2172. SendMessage( GetDlgItem( _hDlg, IDC_ADD_DRIVER ),
  2173. BM_SETSTYLE,
  2174. MAKEWPARAM( BS_DEFPUSHBUTTON, 0 ),
  2175. MAKELPARAM( TRUE, 0 ) );
  2176. SetFocus( GetDlgItem( _hDlg, IDC_ADD_DRIVER ) );
  2177. }
  2178. return bStatus;
  2179. }
  2180. BOOL
  2181. TServerDrivers::
  2182. bHandleUpdateDriver(
  2183. UINT uMsg,
  2184. WPARAM wParam,
  2185. LPARAM lParam
  2186. )
  2187. {
  2188. DBGMSG( DBG_TRACE, ( "TServerDrivers::bHandleUpdateDriver\n" ) );
  2189. TStatusB bStatus;
  2190. bStatus DBGNOCHK = FALSE;
  2191. //
  2192. // Get a list of the selected items.
  2193. //
  2194. UINT nCount = 0;
  2195. TDriverTransfer DriverTransfer;
  2196. bStatus DBGCHK = _DriversLV.bGetSelectedDriverInfo( DriverTransfer, &nCount );
  2197. DBGMSG( DBG_TRACE, ( "Selected count %d\n", nCount ) );
  2198. //
  2199. // Warn the user that they are about to update a driver from the system permently.
  2200. //
  2201. if( bStatus && nCount )
  2202. {
  2203. bStatus DBGNOCHK = bWarnUserDriverUpdate( DriverTransfer.DriverInfoList_pGetByIndex( 0 ), nCount );
  2204. }
  2205. //
  2206. // Delete the driver if the count is non zero.
  2207. //
  2208. if( bStatus && nCount )
  2209. {
  2210. //
  2211. // Initialize the list iterator.
  2212. //
  2213. TIter Iter;
  2214. DriverTransfer.DriverInfoList_vIterInit( Iter );
  2215. TDriverInfo *pDriverInfo;
  2216. for( Iter.vNext(); Iter.bValid(); Iter.vNext() )
  2217. {
  2218. pDriverInfo = DriverTransfer.DriverInfoList_pConvert( Iter );
  2219. DBGMSG( DBG_TRACE, ( "Selected Driver Name: "TSTR"\n", (LPCTSTR)pDriverInfo->strName() ) );
  2220. //
  2221. // Mark all the selected driver as update canidates.
  2222. //
  2223. pDriverInfo->vSetInfoState( TDriverInfo::kUpdate );
  2224. }
  2225. }
  2226. //
  2227. // Return the selected items back to the list view.
  2228. //
  2229. _DriversLV.vReturnDriverInfoToListView( DriverTransfer );
  2230. return bStatus;
  2231. }
  2232. BOOL
  2233. TServerDrivers::
  2234. bHandleDriverDetails(
  2235. UINT uMsg,
  2236. WPARAM wParam,
  2237. LPARAM lParam
  2238. )
  2239. {
  2240. DBGMSG( DBG_TRACE, ( "TServerDrivers::bHandleDetails\n" ) );
  2241. TStatusB bStatus;
  2242. TDriverInfo *pDriverInfo;
  2243. TDriversLV::THandle Handle;
  2244. for( bStatus DBGNOCHK = TRUE; bStatus ; )
  2245. {
  2246. bStatus DBGNOCHK = _DriversLV.bGetSelectedDriverInfo( &pDriverInfo, Handle );
  2247. if( bStatus )
  2248. {
  2249. TDriverDetails Details( _hDlg, pDriverInfo );
  2250. if( VALID_OBJ( Details ) )
  2251. {
  2252. Details.bDoModal();
  2253. }
  2254. }
  2255. }
  2256. return TRUE;
  2257. }
  2258. BOOL
  2259. TServerDrivers::
  2260. bWarnUserDriverDeletion(
  2261. IN TDriverInfo *pDriverInfo,
  2262. IN UINT nCount
  2263. ) const
  2264. {
  2265. //
  2266. // If there are multiple items selected then the warning message
  2267. // is changed.
  2268. //
  2269. INT iMsg = nCount == 1 ? IDS_ERR_DELETE_PRINTER_DRIVER : IDS_ERR_DELETE_PRINTER_DRIVERN;
  2270. //
  2271. // Return success of the user was warned and decided to complete
  2272. // the printer driver removal.
  2273. //
  2274. return iMessage( _hDlg,
  2275. IDS_SERVER_PROPERTIES_TITLE,
  2276. iMsg,
  2277. MB_YESNO | MB_ICONQUESTION,
  2278. kMsgNone,
  2279. NULL,
  2280. static_cast<LPCTSTR>( pDriverInfo->strName() ) ) == IDYES ? TRUE : FALSE;
  2281. }
  2282. BOOL
  2283. TServerDrivers::
  2284. bWarnUserDriverUpdate(
  2285. IN TDriverInfo *pDriverInfo,
  2286. IN UINT nCount
  2287. ) const
  2288. {
  2289. //
  2290. // If there are multiple items selected then the warning message
  2291. // is changed.
  2292. //
  2293. INT iMsg = nCount == 1 ? IDS_ERR_UPDATE_PRINTER_DRIVER : IDS_ERR_UPDATE_PRINTER_DRIVERN;
  2294. //
  2295. // Return success of the user was warned and decided to complete
  2296. // the printer driver removal.
  2297. //
  2298. return iMessage( _hDlg,
  2299. IDS_SERVER_PROPERTIES_TITLE,
  2300. iMsg,
  2301. MB_YESNO | MB_ICONQUESTION,
  2302. kMsgNone,
  2303. NULL,
  2304. static_cast<LPCTSTR>( pDriverInfo->strName() ) ) == IDYES ? TRUE : FALSE;
  2305. }
  2306. /********************************************************************
  2307. Server Driver Notify
  2308. ********************************************************************/
  2309. TServerDriverNotify::
  2310. TServerDriverNotify(
  2311. TServerDrivers *pServerDrivers
  2312. ) : _pServerDrivers( pServerDrivers ),
  2313. _pDi( NULL ),
  2314. _uNotifyCount( 0 ),
  2315. _bActionFailed( FALSE )
  2316. {
  2317. }
  2318. TServerDriverNotify::
  2319. ~TServerDriverNotify(
  2320. VOID
  2321. )
  2322. {
  2323. //
  2324. // Ensure we release the printer driver installation object.
  2325. //
  2326. delete _pDi;
  2327. }
  2328. /*++
  2329. Routine Name:
  2330. bNotify
  2331. Routine Description:
  2332. Called for all driver info classes in the list view.
  2333. Arguments:
  2334. pDriverInfo - Pointer to driver info class.
  2335. Return Value:
  2336. TRUE continue for the remaing driver info classes.
  2337. FALSE stop notification.
  2338. --*/
  2339. BOOL
  2340. TServerDriverNotify::
  2341. bNotify(
  2342. IN TDriverInfo *pDriverInfo
  2343. )
  2344. {
  2345. DBGMSG( DBG_TRACE, ( "TServerDriverNotify::bNotify\n" ) );
  2346. //
  2347. // Adjust the notify count, used for detection the multi selection
  2348. //
  2349. //
  2350. _uNotifyCount++;
  2351. BOOL bStatus = TRUE;
  2352. INT iMessageId = 0;
  2353. switch( pDriverInfo->vGetInfoState() )
  2354. {
  2355. case TDriverInfo::kRemove:
  2356. bStatus = bRemove( pDriverInfo );
  2357. iMessageId = IDS_ERR_ALL_DRIVER_NOT_REMOVED;
  2358. break;
  2359. case TDriverInfo::kAdd:
  2360. bStatus = bInstall( pDriverInfo );
  2361. iMessageId = IDS_ERR_ALL_DRIVER_NOT_INSTALLED;
  2362. break;
  2363. case TDriverInfo::kUpdate:
  2364. bStatus = bUpdate( pDriverInfo );
  2365. iMessageId = IDS_ERR_ALL_DRIVER_NOT_UPDATED;
  2366. break;
  2367. default:
  2368. bStatus = TRUE;
  2369. iMessageId = 0;
  2370. break;
  2371. }
  2372. if( !bStatus )
  2373. {
  2374. if( iMessageId && GetLastError() != ERROR_CANCELLED )
  2375. {
  2376. //
  2377. // Display the error message.
  2378. //
  2379. iMessage( _pServerDrivers->_hDlg,
  2380. IDS_SERVER_PROPERTIES_TITLE,
  2381. iMessageId,
  2382. MB_OK|MB_ICONSTOP,
  2383. kMsgGetLastError,
  2384. NULL,
  2385. static_cast<LPCTSTR>( pDriverInfo->strName() ),
  2386. static_cast<LPCTSTR>( pDriverInfo->strEnvironment() ),
  2387. static_cast<LPCTSTR>( pDriverInfo->strVersion() ) );
  2388. }
  2389. _bActionFailed = TRUE;
  2390. //
  2391. // Currently we continue if an error occurred.
  2392. //
  2393. bStatus = TRUE;
  2394. }
  2395. return bStatus;
  2396. }
  2397. BOOL
  2398. TServerDriverNotify::
  2399. bInstall(
  2400. IN TDriverInfo *pDriverInfo
  2401. )
  2402. {
  2403. DBGMSG( DBG_TRACE, ( "TServerDriverNotify::bInstall\n" ) );
  2404. SPLASSERT( FALSE );
  2405. return TRUE;
  2406. }
  2407. BOOL
  2408. TServerDriverNotify::
  2409. bRemove(
  2410. IN TDriverInfo *pDriverInfo
  2411. )
  2412. {
  2413. DBGMSG( DBG_TRACE, ( "TServerDriverNotify::bRemove\n" ) );
  2414. TStatusB bStatus;
  2415. bStatus DBGNOCHK = TRUE;
  2416. //
  2417. // Delete the specfied printer driver.
  2418. //
  2419. bStatus DBGCHK = DeletePrinterDriverEx( (LPTSTR)_pServerDrivers->_pServerData->pszServerName(),
  2420. (LPTSTR)(LPCTSTR)pDriverInfo->strEnv(),
  2421. (LPTSTR)(LPCTSTR)pDriverInfo->strName(),
  2422. DPD_DELETE_UNUSED_FILES|DPD_DELETE_SPECIFIC_VERSION,
  2423. pDriverInfo->dwVersion());
  2424. //
  2425. // If we are trying this action on a down level spooler.
  2426. //
  2427. if( !bStatus && GetLastError() == RPC_S_PROCNUM_OUT_OF_RANGE )
  2428. {
  2429. bStatus DBGCHK = DeletePrinterDriver( (LPTSTR)_pServerDrivers->_pServerData->pszServerName(),
  2430. (LPTSTR)(LPCTSTR)pDriverInfo->strEnv(),
  2431. (LPTSTR)(LPCTSTR)pDriverInfo->strName() );
  2432. }
  2433. //
  2434. // If the driver was deleted then mark the driver structure as removed.
  2435. //
  2436. if( bStatus )
  2437. {
  2438. pDriverInfo->vSetInfoState( TDriverInfo::kRemoved );
  2439. }
  2440. return bStatus;
  2441. }
  2442. BOOL
  2443. TServerDriverNotify::
  2444. bUpdate(
  2445. IN TDriverInfo *pDriverInfo
  2446. )
  2447. {
  2448. DBGMSG( DBG_TRACE, ( "TServerDriverNotify::bUpdate\n" ) );
  2449. TStatusB bStatus;
  2450. DWORD dwEncode = 0;
  2451. DWORD dwPrevInstallFlags = 0;
  2452. bStatus DBGNOCHK = TRUE;
  2453. //
  2454. // Lazy load the printer drivers installation class.
  2455. //
  2456. if( !_pDi )
  2457. {
  2458. _pDi = new TPrinterDriverInstallation( _pServerDrivers->_pServerData->pszServerName(),
  2459. _pServerDrivers->_hDlg );
  2460. bStatus DBGNOCHK = VALID_PTR( _pDi );
  2461. }
  2462. if( bStatus )
  2463. {
  2464. DBGMSG( DBG_TRACE, ( "Installing driver "TSTR"\n", (LPCTSTR)pDriverInfo->_strName ) );
  2465. //
  2466. // Encode the printer driver architercure and version
  2467. //
  2468. bStatus DBGCHK = bEncodeArchVersion( pDriverInfo->_strEnv,
  2469. pDriverInfo->_dwVersion,
  2470. &dwEncode );
  2471. //
  2472. // Get the current install flags.
  2473. //
  2474. dwPrevInstallFlags = _pDi->GetInstallFlags();
  2475. //
  2476. // We do not copy the inf for version 2 drivers.
  2477. //
  2478. if( GetDriverVersion( dwEncode ) == 2 )
  2479. {
  2480. //
  2481. // We don't copy the inf for version 2 drivers.
  2482. //
  2483. _pDi->SetInstallFlags( DRVINST_DONOTCOPY_INF);
  2484. }
  2485. //
  2486. // On NT5 and greater we can overwrite all the driver files,
  2487. // however on less than NT5 we can only copy newer files.
  2488. //
  2489. DWORD dwAddPrinterDriverFlags = APD_COPY_ALL_FILES;
  2490. DWORD dwCurrentDriverEncode = 0;
  2491. if( _pDi->bGetCurrentDriverEncode( &dwCurrentDriverEncode ) )
  2492. {
  2493. if( GetDriverVersion( dwCurrentDriverEncode ) <= 2 )
  2494. {
  2495. dwAddPrinterDriverFlags = APD_COPY_NEW_FILES;
  2496. }
  2497. }
  2498. //
  2499. // Select and install the printer driver.
  2500. //
  2501. BOOL bOfferReplacementDriver = FALSE;
  2502. dwAddPrinterDriverFlags |= APD_INSTALL_WARNED_DRIVER;
  2503. bStatus DBGCHK = _pDi->bSetDriverName( pDriverInfo->_strName ) &&
  2504. _pDi->bInstallDriver( &pDriverInfo->_strName, bOfferReplacementDriver,
  2505. FALSE, _pServerDrivers->_hDlg, dwEncode, dwAddPrinterDriverFlags, TRUE );
  2506. if( bStatus )
  2507. {
  2508. //
  2509. // Indicate this driver has been installed.
  2510. //
  2511. pDriverInfo->vSetInfoState( TDriverInfo::kInstalled );
  2512. }
  2513. //
  2514. // Restore the previous install flags.
  2515. //
  2516. _pDi->SetInstallFlags( dwPrevInstallFlags );
  2517. }
  2518. return bStatus;
  2519. }
  2520. /********************************************************************
  2521. Server property windows.
  2522. ********************************************************************/
  2523. TServerWindows::
  2524. TServerWindows(
  2525. IN TServerData *pServerData
  2526. ) : _pServerData( pServerData ),
  2527. _Forms( pServerData ),
  2528. _Ports( pServerData ),
  2529. _Settings( pServerData ),
  2530. _Drivers( pServerData )
  2531. {
  2532. }
  2533. TServerWindows::
  2534. ~TServerWindows(
  2535. )
  2536. {
  2537. }
  2538. /*++
  2539. Routine Name:
  2540. bBuildPages
  2541. Routine Description:
  2542. Builds the document property windows.
  2543. Arguments:
  2544. None - class specific.
  2545. Return Value:
  2546. TRUE pages built ok, FALSE failure building pages.
  2547. --*/
  2548. BOOL
  2549. TServerWindows::
  2550. bBuildPages(
  2551. VOID
  2552. )
  2553. {
  2554. DBGMSG( DBG_TRACE, ( "TServerWindows bBuildPages\n") );
  2555. struct SheetInitializer {
  2556. MGenericProp *pSheet;
  2557. INT iDialog;
  2558. };
  2559. SheetInitializer aSheetInit[] = {
  2560. {&_Forms, DLG_FORMS },
  2561. {&_Ports, DLG_SERVER_PORTS },
  2562. {&_Drivers, DLG_SERVER_DRIVERS },
  2563. {&_Settings, DLG_SERVER_SETTINGS },
  2564. {NULL, NULL, }
  2565. };
  2566. BOOL bReturn = FALSE;
  2567. BOOL bSheetsDestroyed = FALSE;
  2568. PROPSHEETHEADER psh;
  2569. HPROPSHEETPAGE ahpsp[COUNTOF( aSheetInit )];
  2570. PROPSHEETPAGE psp;
  2571. ZeroMemory( &psp, sizeof( psp ));
  2572. ZeroMemory( &psh, sizeof( psh ));
  2573. ZeroMemory( ahpsp, sizeof( ahpsp ));
  2574. psh.dwSize = sizeof( psh );
  2575. psh.hwndParent = _pServerData->hwnd();
  2576. psh.dwFlags = PSH_USEHICON | PSH_PROPTITLE;
  2577. psh.phpage = ahpsp;
  2578. psh.hIcon = _pServerData->hDefaultSmallIcon();
  2579. psh.nStartPage = _pServerData->uStartPage();
  2580. psh.hInstance = ghInst;
  2581. psh.pszCaption = (LPCTSTR)_pServerData->strTitle();
  2582. psh.nPages = COUNTOF( ahpsp );
  2583. psp.dwSize = sizeof( psp );
  2584. psp.hInstance = ghInst;
  2585. psp.pfnDlgProc = MGenericProp::SetupDlgProc;
  2586. //
  2587. // Create the property sheets.
  2588. //
  2589. for( UINT i = 0; i < COUNTOF( ahpsp ); ++i ){
  2590. psp.pszTemplate = MAKEINTRESOURCE( aSheetInit[i].iDialog );
  2591. psp.lParam = (LPARAM)(MGenericProp*)aSheetInit[i].pSheet;
  2592. ahpsp[i] = CreatePropertySheetPage( &psp );
  2593. }
  2594. //
  2595. // Insure the index matches the number of pages.
  2596. //
  2597. SPLASSERT( i == psh.nPages );
  2598. //
  2599. // Verify all pages were created.
  2600. //
  2601. for( i = 0; i < COUNTOF( ahpsp ); ++i ){
  2602. if( !ahpsp[i] ){
  2603. DBGMSG( DBG_WARN, ( "Server Property sheet Unable to create page %d\n", i ));
  2604. goto Done;
  2605. }
  2606. }
  2607. //
  2608. // Indicate we do not have to distory the property sheets.
  2609. //
  2610. bSheetsDestroyed = TRUE;
  2611. //
  2612. // Display the property sheets.
  2613. //
  2614. if( PropertySheet( &psh ) < 0 ){
  2615. DBGMSG( DBG_WARN, ( "Server Property Sheet failed %d\n", GetLastError()));
  2616. vShowResourceError( _pServerData->hwnd() );
  2617. } else {
  2618. //
  2619. // Check if the reboot flag was returned.
  2620. //
  2621. if( _pServerData->_bRebootRequired ) {
  2622. //
  2623. // Display message, reboot neccessary.
  2624. //
  2625. if (_pServerData->pszServerName()) {
  2626. //
  2627. // if the server name is not NULL, we assume it is a remote printers folder.
  2628. // This is not true if user opens the local printers folder from
  2629. // \\local-machine-name, but this is a rare case that we can ignore.
  2630. //
  2631. iMessage( _pServerData->hwnd(),
  2632. IDS_SERVER_PROPERTIES_TITLE,
  2633. IDS_SERVER_SETTINGS_CHANGED_REMOTE,
  2634. MB_ICONEXCLAMATION,
  2635. kMsgNone,
  2636. NULL,
  2637. _pServerData->pszServerName()
  2638. );
  2639. }
  2640. else {
  2641. iMessage( _pServerData->hwnd(),
  2642. IDS_SERVER_PROPERTIES_TITLE,
  2643. IDS_SERVER_SETTINGS_CHANGED,
  2644. MB_ICONEXCLAMATION,
  2645. kMsgNone,
  2646. NULL
  2647. );
  2648. }
  2649. }
  2650. bReturn = TRUE;
  2651. }
  2652. Done:
  2653. //
  2654. // If Sheets weren't destoryed, do it now.
  2655. //
  2656. if( !bSheetsDestroyed ){
  2657. for( i = 0; i < COUNTOF( ahpsp ); ++i ){
  2658. if( ahpsp[i] ){
  2659. DestroyPropertySheetPage( ahpsp[i] );
  2660. }
  2661. }
  2662. }
  2663. return bReturn;
  2664. }
  2665. /*++
  2666. Routine Name:
  2667. bDisplayPages
  2668. Routine Description:
  2669. Displays the document property pages.
  2670. Arguments:
  2671. None.
  2672. Return Value:
  2673. TRUE if pages were displayed, FALSE
  2674. --*/
  2675. BOOL
  2676. TServerWindows::
  2677. bDisplayPages(
  2678. VOID
  2679. )
  2680. {
  2681. return TRUE;
  2682. }
  2683. /*++
  2684. Routine Name:
  2685. bValid
  2686. Routine Description:
  2687. Returns if class and its dat members are vaild.
  2688. Arguments:
  2689. None.
  2690. Return Value:
  2691. TRUE - class is valid, FALSE class is invalid.
  2692. --*/
  2693. BOOL
  2694. TServerWindows::
  2695. bValid(
  2696. VOID
  2697. )
  2698. {
  2699. //
  2700. // Validated all the known pages.
  2701. //
  2702. if( VALID_OBJ( _Forms ) &&
  2703. VALID_OBJ( _Ports ) &&
  2704. VALID_OBJ( _Drivers ) &&
  2705. VALID_OBJ( _Settings ) ){
  2706. return TRUE;
  2707. }
  2708. return FALSE;
  2709. }