|
|
/*++
Copyright (C) Microsoft Corporation, 1995 - 1999 All rights reserved.
Module Name:
svrprop.cxx
Abstract:
Server Properties
Author:
Steve Kiraly (SteveKi) 11/15/95
Revision History:
--*/
#include "precomp.hxx"
#pragma hdrstop
#include "psetup.hxx"
#include "drvver.hxx"
#include "drvsetup.hxx"
#include "portslv.hxx"
#include "portdlg.hxx"
#include "driverif.hxx"
#include "driverlv.hxx"
#include "driverdt.hxx"
#include "svrprop.hxx"
#include "forms.hxx"
#include "time.hxx"
#include "instarch.hxx"
#include "dsinterf.hxx"
#include "prtprop.hxx"
#include "archlv.hxx"
#include "detect.hxx"
#include "setup.hxx"
#include "prndata.hxx"
#include "persist.hxx"
/*++
Routine Description:
WOW64 version.
see vServerPropPages below.
Arguments:
see vServerPropPages below.
Return Value:
--*/
VOID vServerPropPagesWOW64( IN HWND hwnd, IN LPCTSTR pszServerName, IN INT iCmdShow, IN LPARAM lParam ) { //
// This function potentially may load the driver UI so we call a private API
// exported by winspool.drv, which will RPC the call to a special 64 bit surrogate
// process where the 64 bit driver can be loaded.
//
CDllLoader dll(TEXT("winspool.drv")); if (dll) { ptr_PrintUIServerPropPages pfn = (ptr_PrintUIServerPropPages )dll.GetProcAddress(ord_PrintUIServerPropPages);
if (pfn) { // call into winspool.drv
pfn(hwnd, pszServerName, iCmdShow, lParam); } } }
/*++
Routine Description:
Native version.
see vServerPropPages below.
Arguments:
see vServerPropPages below.
Return Value:
--*/
VOID vServerPropPagesNative( IN HWND hwnd, IN LPCTSTR pszServerName, IN INT iCmdShow, IN LPARAM lParam ) { DBGMSG( DBG_TRACE, ( "vServerPropPages\n") );
BOOL bModal = FALSE; DWORD dwSheetNumber = LOWORD( lParam ); //
// If the high word is non zero then dialog is modal.
//
if( HIWORD( lParam ) ) { bModal = TRUE; }
//
// Create the server specific data.
//
TServerData *pServerData = new TServerData( pszServerName, iCmdShow, dwSheetNumber, hwnd, bModal ); //
// If errors were encountered creating document data.
//
if( !VALID_PTR( pServerData )){ goto Fail; }
//
// If lparam is has the high word non zero the dialog is modal.
//
if( bModal ) {
//
// If a failure occured then the message has already been displayed,
// therefore we just exit.
//
iServerPropPagesProc( pServerData ); return;
} else {
//
// Create the thread which handles the UI. iServerPropPagesProc adopts
// pServerData, therefore only on thread creation failure do we
// release the data back to the heap.
//
DWORD dwIgnore; HANDLE hThread; hThread = TSafeThread::Create( NULL, 0, (LPTHREAD_START_ROUTINE)iServerPropPagesProc, pServerData, 0, &dwIgnore );
//
// Check thread creation.
//
if( !hThread ){ goto Fail; }
//
// Thread handle is not needed.
//
CloseHandle( hThread ); return; }
Fail:
if( !pServerData ){
vShowResourceError( hwnd );
} else {
iMessage( hwnd, IDS_SERVER_PROPERTIES_TITLE, IDS_ERR_SERVER_PROP_CANNOT_VIEW, MB_OK|MB_ICONSTOP, kMsgGetLastError, NULL ); }
delete pServerData;
}
/*++
Routine Description:
This function opens the property sheet of specified server.
We can't guarentee that this propset will perform all lengthy operations in a worker thread (we synchronously call things like ConfigurePort). Therefore, we spawn off a separate thread to handle document properties.
Arguments:
hwnd - Specifies the parent window (optional). pszPrinter - Specifies the printer name (e.g., "My HP LaserJet IIISi"). nCmdShow - Initial show state lParam - May specify a sheet number to open to or if the high word is non zero then dialog is modal.
Return Value:
--*/ VOID vServerPropPages( IN HWND hwnd, IN LPCTSTR pszServerName, IN INT iCmdShow, IN LPARAM lParam ) { if (IsRunningWOW64()) { vServerPropPagesWOW64(hwnd, pszServerName, iCmdShow, lParam); } else { vServerPropPagesNative(hwnd, pszServerName, iCmdShow, lParam); } }
/*++
aRoutine Name:
iServerPropPagesProc
Routine Description:
This is the routine called by the create thread call to display the server property sheets.
Arguments:
pServerData - Pointer to the Server data set used by all property sheets.
Return Value:
TRUE - if the property sheets were displayed. FALSE - error creating and displaying property sheets.
--*/ INT WINAPI iServerPropPagesProc( IN TServerData *pServerData ADOPT ) { DBGMSG( DBG_TRACE, ( "iServerPropPagesProc\n") );
BOOL bStatus = pServerData->bRegisterWindow( PRINTER_PIDL_TYPE_PROPERTIES );
if( bStatus ){
//
// Check if the window is already present.
//
if( pServerData->bIsWindowPresent() ){ DBGMSG( DBG_TRACE, ( "iServerPropPagesProc: currently running.\n" ) ); bStatus = FALSE; } }
if( bStatus ) {
bStatus = pServerData->bLoad();
if( !bStatus ){
iMessage( pServerData->_hwnd, IDS_SERVER_PROPERTIES_TITLE, IDS_ERR_SERVER_PROP_CANNOT_VIEW, MB_OK|MB_ICONSTOP|MB_SETFOREGROUND, kMsgGetLastError, NULL ); } else {
//
// Create the Server property sheet windows.
//
TServerWindows ServerWindows( pServerData );
//
// Were the document windows create
//
if( !VALID_OBJ( ServerWindows ) ){
iMessage( pServerData->_hwnd, IDS_SERVER_PROPERTIES_TITLE, IDS_ERR_SERVER_PROP_CANNOT_VIEW, MB_OK|MB_ICONSTOP|MB_SETFOREGROUND, kMsgGetLastError, NULL );
bStatus = FALSE; }
//
// Build the property pages.
//
if( bStatus ){ if( !ServerWindows.bBuildPages( ) ){ vShowResourceError( NULL ); bStatus = FALSE; } }
//
// Display the property pages.
//
if( bStatus ){ if( !ServerWindows.bDisplayPages( ) ){ vShowResourceError( NULL ); bStatus = FALSE; } } } }
//
// Ensure we release the document data.
// We have adopted pSeverData, so we must free it.
//
delete pServerData;
return bStatus; }
/*++
Routine Name:
TServerData
Routine Description:
Server data property sheet constructor.
Arguments:
pszPrinterName - Name of printer or queue where jobs reside. JobId - Job id to display properties of. iCmdShow - Show dialog style. lParam - Indicates which page to display initialy
Return Value:
Nothing.
--*/
TServerData:: TServerData( IN LPCTSTR pszServerName, IN INT iCmdShow, IN LPARAM lParam, IN HWND hwnd, IN BOOL bModal ) : MSingletonWin( pszServerName, hwnd, bModal ), _iCmdShow( iCmdShow ), _uStartPage( (UINT)lParam ), _bValid( FALSE ), _hPrintServer( NULL ), _hDefaultSmallIcon( NULL ), _bCancelButtonIsClose( FALSE ), _dwDriverVersion( 0 ), _bRemoteDownLevel( FALSE ), _bRebootRequired( FALSE ) { if( !MSingletonWin::bValid( )){ return; }
//
// Retrieve icons.
//
LoadPrinterIcons( _strPrinterName, NULL, &_hDefaultSmallIcon );
SPLASSERT( _hDefaultSmallIcon );
//
// Set the server name to NULL if it's local.
//
_pszServerName = _strPrinterName.bEmpty() ? NULL : (LPCTSTR)_strPrinterName;
//
// Get the machine name.
//
vCreateMachineName( _strPrinterName, _pszServerName ? FALSE : TRUE, _strMachineName );
//
// Get the print servers driver version, the driver
// version corresponds to the actual spooler version, we
// are using this for downlevel detection.
//
if( !bGetCurrentDriver( _pszServerName, &_dwDriverVersion ) ) { //
// Note this is not a fatal error, we won't have the
// add/delete/configure ports buttons enabled.
//
DBGMSG( DBG_WARN, ( "Get driver version failed.\n" ) ); }
//
// Check if we are remotely administering a downlevel machine
//
_bRemoteDownLevel = ( bIsRemote( _pszServerName ) && ( GetDriverVersion( _dwDriverVersion ) <= 2 ) ) ? TRUE : FALSE;
_bValid = TRUE; }
/*++
Routine Name:
~TServerData
Routine Description:
Stores the document data back to the server.
Arguments:
None.
Return Value:
Nothing.
--*/
TServerData:: ~TServerData( VOID ) { //
// Insure we close the print server.
//
if( _hPrintServer ){ ClosePrinter( _hPrintServer ); }
//
// Destroy the printer icon.
//
if( _hDefaultSmallIcon ){ DestroyIcon( _hDefaultSmallIcon ); }
}
/*++
Routine Name:
bValid
Routine Description:
Returns objects state.
Arguments:
None.
Return Value:
TRUE object is in valid state, FALSE object is not valid.
--*/ BOOL TServerData:: bValid( VOID ) { return _bValid; }
/*++
Routine Name:
vCreateMachineName
Routine Description:
Create the machine name for display. bLocal indicates the provided server name is for the local machine, Since a local machine is often represented by the NULL pointer we will get the computer name if a local server name is passed. If the bLocal is false strPrinterName contains the name of the remote printer server.
Arguments:
strServerName - Name of the print server. bLocal - TRUE str server name is local, or FALSE strPrinterName is name of remote print server. strMachineName - Target of the fetched machine name.
Return Value:
Nothing.
--*/ VOID TServerData:: vCreateMachineName( IN const TString &strServerName, IN BOOL bLocal, IN TString &strMachineName ) { TStatusB bStatus; LPCTSTR pszBuffer;
//
// If a server name was provided then set the title to
// the server name, otherwise get the computer name.
//
if( !bLocal ){
//
// Copy the server name.
//
bStatus DBGCHK = strMachineName.bUpdate( strServerName );
} else {
//
// Server name is null, therefore it is the local machine.
//
bStatus DBGCHK = bGetMachineName( strMachineName ); }
//
// Remove any leading slashes.
//
pszBuffer = (LPCTSTR)strMachineName; for( ; pszBuffer && (*pszBuffer == TEXT( '\\' )); pszBuffer++ ) ;
//
// Update the name we display on the sheets.
//
bStatus DBGCHK = strMachineName.bUpdate( pszBuffer ); }
/*++
Routine Name:
bLoad
Routine Description:
Loads the property sheet specific data.
Arguments:
None.
Return Value:
TRUE - Data loaded successfully, FALSE - Data was not loaded.
--*/ BOOL TServerData:: bLoad( VOID ) { DBGMSG( DBG_TRACE, ( "TServerData::bLoad\n") );
//
// Attempt to open print server with full access.
//
TStatus Status; DWORD dwAccess = 0; Status DBGCHK = TPrinter::sOpenPrinter( pszServerName(), &dwAccess, &_hPrintServer );
if( Status == ERROR_SUCCESS ){
//
// Save administrator capability flag.
//
bAdministrator() = (dwAccess == SERVER_ALL_ACCESS);
//
// Get the default title from the resource file.
//
if( !_strTitle.bLoadString( ghInst, IDS_SERVER_SETTINGS_TITLE ) ){ DBGMSG( DBG_WARN, ( "strTitle().bLoadString failed with %d\n", GetLastError () ) ); vShowResourceError( hwnd() ); }
//
// Null terminate the title buffer.
//
TCHAR szTitle[kStrMax+kPrinterBufMax] = {0}; UINT nSize = COUNTOF( szTitle );
//
// Create the property sheet title.
//
if( pszServerName() ){ _tcscpy( szTitle, pszServerName() ); _tcscat( szTitle, TEXT( "\\" ) ); }
//
// Build the title buffer.
//
_tcscat( szTitle, _strTitle );
//
// Format the title similar to the shell.
//
ConstructPrinterFriendlyName( szTitle, szTitle, &nSize );
//
// Update the property sheet title.
//
if( !_strTitle.bUpdate( szTitle ) ){ DBGMSG( DBG_WARN, ( "strTitle().bUpdate failed with %d\n", GetLastError () ) ); vShowResourceError( hwnd() ); } }
return Status == ERROR_SUCCESS; }
/*++
Routine Name:
bStore
Routine Description:
Stores the document data from back to the printer system.
Arguments:
None.
Return Value:
TRUE - Server data stored successfully, FALSE - if document data was not stored.
--*/ BOOL TServerData:: bStore( VOID ) { return TRUE; }
/********************************************************************
Server Property Base Class
********************************************************************/ /*++
Routine Name:
TServerProp
Routine Description:
Initialized the server property sheet base class
Arguments:
pServerData - Pointer to server data needed for all property sheets.
Return Value:
None.
--*/ TServerProp:: TServerProp( IN TServerData* pServerData ) : _pServerData( pServerData ) { }
/*++
Routine Name:
~TServerProp
Routine Description:
Base class desctuctor.
Arguments:
None.
Return Value:
Nothing.
--*/ TServerProp:: ~TServerProp( ) {
}
/*++
Routine Name:
bValid
Routine Description:
Determis if an object is in a valid state.
Arguments:
None.
Return Value:
TRUE object is valid. FALSE object is not valid. --*/ BOOL TServerProp:: bValid( VOID ) { return ( _pServerData ) ? TRUE : FALSE; }
/*++
Routine Name:
vCancelToClose
Routine Description:
Change the cancel button to close, the user has basically made a change that cannot be undone using the cancel button.
Arguments:
None.
Return Value:
Nothing.
--*/ VOID TServerProp:: vCancelToClose( IN HWND hDlg ) { PropSheet_CancelToClose( GetParent( hDlg ) ); _pServerData->bCancelButtonIsClose() = TRUE; }
/*++
Routine Name:
bHandleMessage
Routine Description:
Base class message handler. This routine is called by derived classes who do not want to handle the message.
Arguments:
uMsg - Windows message wParam - Word parameter lParam - Long parameter
Return Value:
TRUE if message was handled, FALSE if message not handled.
--*/ BOOL TServerProp:: bHandleMessage( IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ) { BOOL bStatus = TRUE;
UNREFERENCED_PARAMETER( wParam );
switch( uMsg ){
//
// Set the values on the UI.
//
case WM_INITDIALOG: bStatus = bSetUI(); break;
//
// Handle help and context help.
//
case WM_HELP: case WM_CONTEXTMENU: bStatus = PrintUIHelp( uMsg, _hDlg, wParam, lParam ); break;
//
// Save the data.
//
case WM_DESTROY: bStatus = FALSE; break;
case WM_NOTIFY: switch( ((LPNMHDR)lParam)->code ) { //
// User switched to the next page.
//
case PSN_KILLACTIVE: bStatus = bReadUI(); vSetDlgMsgResult( !bStatus ); //
// Must return true, to make the property sheet
// control look at the dlg message result.
//
bStatus = TRUE; break;
//
// User has chosen the close or apply button.
//
case PSN_APPLY: { LPPSHNOTIFY pPSHNotify = (LPPSHNOTIFY)lParam;
//
// Save the UI to the system.
//
bStatus = bSaveUI();
//
// If there was a failure then switch to this page.
//
if( !bStatus ) { //
// Switch to page with the error.
//
PropSheet_SetCurSelByID( GetParent( _hDlg ), uGetPageId() ); }
//
// If the lParam is true the close button was used to
// dismiss the dialog. Let the dialog exit if the close
// button was clicked and one of the dialogs failed.
//
if( pPSHNotify->lParam == TRUE && bStatus == FALSE ) { //
// If the cancel button is has the closed text, then
// prompt the user if they want to exit on failure.
// The cancel button state is stored in the server data
// because it has to be global to all property sheets.
//
if( _pServerData->bCancelButtonIsClose() ) { //
// Display the error message.
//
if( iMessage( _hDlg, IDS_SERVER_PROPERTIES_TITLE, IDS_ERR_WANT_TO_EXIT, MB_YESNO|MB_ICONSTOP, kMsgNone, NULL ) == IDYES ) { bStatus = TRUE; } } }
//
// Indicate the return value to the property sheet control
//
vSetDlgMsgResult( bStatus == FALSE ? PSNRET_INVALID_NOCHANGEPAGE : PSNRET_NOERROR );
//
// Must return true, to make the property sheet
// control look at the dlg message result.
//
bStatus = TRUE; }
break;
//
// Indicate the user chose the cancel button.
//
case PSN_QUERYCANCEL: bStatus = FALSE; break;
default: bStatus = FALSE; break; } break;
default: bStatus = FALSE; break; }
return bStatus; }
/********************************************************************
Forms Server Property Sheet.
********************************************************************/
/*++
Routine Name:
TServerForms
Routine Description:
Document property sheet derived class.
Arguments:
None.
Return Value:
Nothing.
--*/ TServerForms:: TServerForms( IN TServerData *pServerData ) : TServerProp( pServerData ) { //
// This does forms specific initialization.
//
_p = FormsInit( pServerData->pszServerName(), pServerData->hPrintServer(), pServerData->bAdministrator(), pServerData->strMachineName() ); }
/*++
Routine Name:
~TServerForms
Routine Description:
Document derived class destructor.
Arguments:
None.
Return Value:
Nothing.
--*/
TServerForms:: ~TServerForms( VOID ) { //
// Forms specific termination.
//
FormsFini( _p ); }
/*++
Routine Name:
bValid
Routine Description:
Document property sheet derived class valid object indicator.
Arguments:
None.
Return Value:
Returns the status of the base class.
--*/ BOOL TServerForms:: bValid( VOID ) { return ( _p ) ? TRUE : FALSE; }
/*++
Routine Name:
bSetUI
Routine Description:
Loads the property sheet dialog with the document data information.
Arguments:
None.
Return Value:
TRUE if data loaded successfully, FALSE if error occurred.
--*/ BOOL TServerForms:: bSetUI( VOID )
{ return TRUE; }
/*++
Routine Name:
bReadUI
Routine Description:
Stores the property information to the print server.
Arguments:
Nothing data is contained with in the class.
Return Value:
TRUE if data is stores successfully, FALSE if error occurred.
--*/ BOOL TServerForms:: bReadUI( VOID ) { return TRUE; }
/*++
Routine Name:
bSaveUI
Routine Description:
Saves the UI data to some API call or print server.
Arguments:
Nothing data is contained with in the class.
Return Value:
TRUE if data is stores successfully, FALSE if error occurred.
--*/ BOOL TServerForms:: bSaveUI( VOID ) { // force a save form event.
bHandleMessage( WM_COMMAND, (WPARAM)MAKELPARAM( IDD_FM_PB_SAVEFORM, kMagic ), (LPARAM)GetDlgItem( _hDlg, IDD_FM_PB_SAVEFORM ));
// check to see if failed
return (ERROR_SUCCESS == Forms_GetLastError(_p)); }
/*++
Routine Name:
bHandleMessage
Routine Description:
Server property sheet message handler. This handler only handles events it wants and the base class handle will do the standard message handling.
Arguments:
uMsg - Windows message wParam - Word parameter lParam - Long parameter
Return Value:
TRUE if message was handled, FALSE if message not handled.
--*/
BOOL TServerForms:: bHandleMessage( IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ) { BOOL bStatus = FALSE; LONG_PTR PrevValue;
//
// !!Hack!!
//
// This is code to get the borrowed forms dialog
// code from printman, to work. It is saving our "this" pointer and
// placing the forms specific data in the GWL_USERDATA.
//
PrevValue = GetWindowLongPtr( _hDlg, GWLP_USERDATA );
SetWindowLongPtr( _hDlg, GWLP_USERDATA, (LONG_PTR)_p );
if( uMsg == WM_INITDIALOG ) { lParam = (LPARAM)_p; }
bStatus = FormsDlg( _hDlg, uMsg, wParam, lParam );
SetWindowLongPtr( _hDlg, GWLP_USERDATA, PrevValue );
//
// If the message was handled - check to call PSM_CANCELTOCLOSE
//
if( bStatus && Forms_IsThereCommitedChanges(_p) ) { vCancelToClose( _hDlg ); }
//
// If the message was not handled pass it on to the derrived base class.
//
if( !bStatus ) { bStatus = TServerProp::bHandleMessage( uMsg, wParam, lParam ); }
return bStatus; }
/********************************************************************
Settings Server Property Sheet.
********************************************************************/
/*++
Routine Name:
TServerSettings
Routine Description:
Document property sheet derived class.
Arguments:
None.
Return Value:
Nothing.
--*/ TServerSettings:: TServerSettings( IN TServerData *pServerData ) : TServerProp( pServerData ), _bBeepErrorJobs( FALSE ), _bEventLogging( FALSE ), _bNotifyPrintedJobs( FALSE ), _bNotifyLocalPrintedJobs( FALSE ), _bNotifyNetworkPrintedJobs( TRUE ), _bNotifyPrintedJobsComputer( FALSE ), _bChanged( FALSE ), _bDownLevelServer( TRUE ), _bNewOptionSupport( TRUE ) { }
/*++
Routine Name:
~TServerSettings
Routine Description:
Document derived class destructor.
Arguments:
None.
Return Value:
Nothing.
--*/
TServerSettings:: ~TServerSettings( VOID ) { }
/*++
Routine Name:
bValid
Routine Description:
Document property sheet derived class valid object indicator.
Arguments:
None.
Return Value:
Returns the status of the base class.
--*/ BOOL TServerSettings:: bValid( VOID ) { return TServerProp::bValid(); }
/*++
Routine Name:
bSetUI
Routine Description:
Loads the property sheet dialog with the document data information.
Arguments:
None.
Return Value:
TRUE if data loaded successfully, FALSE if error occurred.
--*/ BOOL TServerSettings:: bSetUI( VOID )
{ return bSetUI( kServerAttributesLoad ); }
/*++
Routine Name:
bSetUI
Routine Description:
Loads the property sheet dialog with the document data information.
Arguments:
The specified load type.
Return Value:
TRUE if data loaded successfully, FALSE if error occurred.
--*/ BOOL TServerSettings:: bSetUI( INT LoadType )
{ DBGMSG( DBG_TRACE, ( "TServerSettings::bSetUI\n") );
//
// Set the printer title.
//
if( !bSetEditText( _hDlg, IDC_SERVER_NAME, _pServerData->strMachineName() )) return FALSE;
//
// Load the server attributes into the class variables. If this fails
// it is assumed the machine is either a downlevel server or something
// went wrong.
//
if( sServerAttributes( LoadType ) == kStatusError ){
//
// Disable the controls.
//
vEnable( FALSE );
//
// Indicate the server is not compatible.
//
_bDownLevelServer = FALSE;
//
// Display the error message.
//
iMessage( _hDlg, IDS_SERVER_PROPERTIES_TITLE, IDS_ERR_SERVER_SETTINGS_NOT_AVAILABLE, MB_OK|MB_ICONSTOP, kMsgNone, NULL );
return FALSE; }
//
// Set the spool directory edit control.
//
if( !bSetEditText( _hDlg, IDC_SERVER_SPOOL_DIRECTORY, _strSpoolDirectory )) { return FALSE; }
//
// Save a copy of the origianl spool directory.
//
if( !_strSpoolDirectoryOrig.bUpdate( _strSpoolDirectory ) ) { return FALSE; }
//
// Reset the changed flag, the message handler sees a edit control
// change message when we set the spool directory.
//
_bChanged = FALSE;
//
// Set check box states.
//
vSetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_ERROR, _bEventLogging & EVENTLOG_ERROR_TYPE ); vSetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_WARN, _bEventLogging & EVENTLOG_WARNING_TYPE ); vSetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_INFO, _bEventLogging & EVENTLOG_INFORMATION_TYPE ); vSetCheck( _hDlg, IDC_SERVER_REMOTE_JOB_ERRORS, _bBeepErrorJobs ); vSetCheck( _hDlg, IDC_SERVER_JOB_NOTIFY, _bNotifyPrintedJobs ); vSetCheck( _hDlg, IDC_SERVER_LOCAL_JOB_NOTIFY, _bNotifyLocalPrintedJobs ); vSetCheck( _hDlg, IDC_SERVER_NETWORK_JOB_NOTIFY, _bNotifyNetworkPrintedJobs ); vSetCheck( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER, _bNotifyPrintedJobsComputer );
//
// In remote case, we don't show the "notify user" check box and move the lower controls up.
//
if( bIsRemote( _pServerData->pszServerName() ) ) { RECT rc; RECT rcUpper; int deltaY;
ShowWindow( GetDlgItem( _hDlg, IDC_SERVER_LOCAL_JOB_NOTIFY ), SW_HIDE ); ShowWindow( GetDlgItem( _hDlg, IDC_SERVER_NETWORK_JOB_NOTIFY ), SW_HIDE );
GetWindowRect( GetDlgItem( _hDlg, IDC_SERVER_NETWORK_JOB_NOTIFY ), &rc ); GetWindowRect( GetDlgItem( _hDlg, IDC_SERVER_REMOTE_JOB_ERRORS ), &rcUpper ); deltaY = rcUpper.bottom - rc.bottom;
MoveWindowWrap( GetDlgItem( _hDlg, IDC_DOWNLEVEL_LINE ), 0, deltaY ); MoveWindowWrap( GetDlgItem( _hDlg, IDC_DOWNLEVEL_TEXT ), 0, deltaY ); MoveWindowWrap( GetDlgItem( _hDlg, IDC_SERVER_JOB_NOTIFY ), 0, deltaY ); MoveWindowWrap( GetDlgItem( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER ), 0, deltaY ); }
//
// Only NT 5.0 and greater supports the SPLREG_NET_POPUP_TO_COMPUTER
//
if( !_bNewOptionSupport ) { ShowWindow( GetDlgItem( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER ), SW_HIDE); }
//
// Enable of disable the UI based on the administrator state.
//
vEnable( _pServerData->bAdministrator() );
return TRUE; }
VOID TServerSettings:: vEnable( BOOL bState ) { //
// Set the UI control state.
//
vEnableCtl( _hDlg, IDC_SERVER_EVENT_LOGGING_ERROR, bState ); vEnableCtl( _hDlg, IDC_SERVER_EVENT_LOGGING_WARN, bState ); vEnableCtl( _hDlg, IDC_SERVER_EVENT_LOGGING_INFO, bState ); vEnableCtl( _hDlg, IDC_SPOOL_FOLDER_TEXT, bState ); vEnableCtl( _hDlg, IDC_SERVER_SPOOL_DIRECTORY, bState ); vEnableCtl( _hDlg, IDC_SERVER_REMOTE_JOB_ERRORS, bState ); vEnableCtl( _hDlg, IDC_DOWNLEVEL_TEXT, bState ); vEnableCtl( _hDlg, IDC_SERVER_JOB_NOTIFY, bState ); vEnableCtl( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER, bState && _bNotifyPrintedJobs ); }
/*++
Routine Name:
bReadUI
Routine Description:
Read the UI data storing it back to this object.
Arguments:
Nothing data is contained with in the class.
Return Value:
TRUE if data is read successfully, FALSE if error occurred.
--*/ BOOL TServerSettings:: bReadUI( VOID ) { DBGMSG( DBG_TRACE, ( "TServerSettings::bReadUI\n") );
TStatusB bStatus;
//
// Read the spool directory edit box.
//
bStatus DBGCHK = bGetEditText( _hDlg, IDC_SERVER_SPOOL_DIRECTORY, _strSpoolDirectory );
//
// Do minor validation on the spool directory.
//
if( _strSpoolDirectory.bEmpty() && _bDownLevelServer ) { //
// Display the error message.
//
iMessage( _hDlg, IDS_SERVER_PROPERTIES_TITLE, IDS_ERR_SERVER_SETTINGS_INVALID_DIR, MB_OK|MB_ICONSTOP, kMsgNone, NULL );
bStatus DBGNOCHK = FALSE; }
if( bStatus ) { //
// Read settings check boxes.
//
_bEventLogging = bGetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_ERROR ) << 0; _bEventLogging |= bGetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_WARN ) << 1; _bEventLogging |= bGetCheck( _hDlg, IDC_SERVER_EVENT_LOGGING_INFO ) << 2; _bBeepErrorJobs = bGetCheck( _hDlg, IDC_SERVER_REMOTE_JOB_ERRORS ); _bNotifyLocalPrintedJobs = bGetCheck( _hDlg, IDC_SERVER_LOCAL_JOB_NOTIFY ); _bNotifyNetworkPrintedJobs = bGetCheck( _hDlg, IDC_SERVER_NETWORK_JOB_NOTIFY ); _bNotifyPrintedJobs = bGetCheck( _hDlg, IDC_SERVER_JOB_NOTIFY ); _bNotifyPrintedJobsComputer = bGetCheck( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER ); }
return bStatus; }
/*++
Routine Name:
bSaveUI
Routine Description:
Saves the UI data with some API call to the print server.
Arguments:
Nothing data is contained with in the class.
Return Value:
TRUE if data is stores successfully, FALSE if error occurred.
--*/ BOOL TServerSettings:: bSaveUI( VOID ) { DBGMSG( DBG_TRACE, ( "TServerSettings::bSaveUI\n") );
BOOL bStatus = TRUE; BOOL bErrorShown = FALSE;
//
// If data was chagned save the settings.
//
if( _bChanged && _bDownLevelServer ) {
if( lstrcmpi(_strSpoolDirectoryOrig, _strSpoolDirectory) ) {
//
// The spooler folder has been changed. Warn the user
// for potential loose of the current printing jobs.
//
INT iResult = iMessage( _hDlg, IDS_SERVER_PROPERTIES_TITLE, IDS_SERVER_PROPERTIES_CHANGESPOOLFOLDER_WARN, MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2, kMsgNone, NULL );
if( IDNO == iResult ) {
//
// The user did not what to continue, don't close the dialog.
//
SetLastError( ERROR_CANCELLED ); bStatus = FALSE;
} }
if( bStatus ) {
switch( sServerAttributes( kServerAttributesStore ) ){
case kStatusCannotSaveUserNotification:
//
// Display the error message.
//
iMessage( _hDlg, IDS_SERVER_PROPERTIES_TITLE, IDS_ERR_GENERIC, MB_OK|MB_ICONHAND, kMsgNone, NULL );
bStatus = FALSE; bErrorShown = TRUE; break;
case kStatusInvalidSpoolDirectory:
//
// Display the error message.
//
iMessage( _hDlg, IDS_SERVER_PROPERTIES_TITLE, IDS_ERR_SERVER_SETTINGS_INVALID_DIR, MB_OK|MB_ICONSTOP, kMsgNone, NULL ); //
// Set focus to control with error.
//
SetFocus( GetDlgItem( _hDlg, IDC_SERVER_SPOOL_DIRECTORY ) ); bStatus = FALSE; bErrorShown = TRUE; break;
case kStatusSuccess:
_bChanged = FALSE; bStatus = TRUE; break;
case kStatusError: default:
bStatus = FALSE; break; }
if( bStatus && _pServerData->bAdministrator() ) {
//
// Update the new original spooler directory
//
bStatus = _strSpoolDirectoryOrig.bUpdate( _strSpoolDirectory ); } } }
if( !bStatus ) {
//
// Display the error message.
//
if( GetLastError() != ERROR_CANCELLED && !bErrorShown ) { iMessage( _hDlg, IDS_SERVER_PROPERTIES_TITLE, IDS_ERR_SERVER_SETTINGS_SAVE, MB_OK|MB_ICONSTOP, kMsgGetLastError, NULL ); } }
return bStatus; }
/*++
Routine Name:
sServerAttributes
Routine Description:
Loads and stores server attributes.
Arguments:
Direction flag either kStore or kLoad pr kDefault
Return Value:
Status values, see EStatus for for details.
--*/
INT TServerSettings:: sServerAttributes( INT iFlag ) { INT iStatus; TStatusH hr;
//
// Create the printer data access class.
//
TPrinterDataAccess Data( _pServerData->_hPrintServer ); TPersist NotifyUser( gszPrinterPositions, TPersist::kCreate|TPersist::kRead|TPersist::kWrite );
//
// Relax the return type checking, BOOL are not REG_DWORD but REG_BINARY
//
Data.RelaxReturnTypeCheck( TRUE );
switch( iFlag ) {
//
// Load from the spooler
//
case kServerAttributesLoad:
hr DBGCHK = Data.Get( SPLREG_DEFAULT_SPOOL_DIRECTORY, _strSpoolDirectory ); hr DBGCHK = Data.Get( SPLREG_BEEP_ENABLED, _bBeepErrorJobs ); hr DBGCHK = Data.Get( SPLREG_EVENT_LOG, _bEventLogging ); hr DBGCHK = Data.Get( SPLREG_NET_POPUP, _bNotifyPrintedJobs );
hr DBGCHK = NotifyUser.bRead( gszLocalPrintNotification, _bNotifyLocalPrintedJobs ) ? S_OK : E_FAIL; hr DBGCHK = NotifyUser.bRead( gszNetworkPrintNotification, _bNotifyNetworkPrintedJobs ) ? S_OK : E_FAIL; hr DBGCHK = Data.Get( SPLREG_NET_POPUP_TO_COMPUTER, _bNotifyPrintedJobsComputer );
//
// If we fail reading the net popup to computer with invalid parameter
// we are talking to a downlevel machine pre nt 5.0 machine. If this
// is the case we simple do not show this option in the UI and continue
// normally.
//
if( FAILED( hr ) && HRESULT_CODE( hr ) == ERROR_INVALID_PARAMETER ) { _bNewOptionSupport = FALSE; }
//
// If were are talking to a downlevel machine pre nt 4.0,
// get printer data calls will fail with error invalid handle. We
// only check the last value read, since this error code should never
// happen on any calls to get printer data.
//
if( FAILED( hr ) && HRESULT_CODE( hr ) == ERROR_INVALID_HANDLE ) { iStatus = kStatusError; } else { iStatus = kStatusSuccess; } break;
//
// Store to the spooler
//
case kServerAttributesStore:
//
// We save this data for local case
//
if( !bIsRemote( _pServerData->pszServerName() ) && VALID_OBJ( NotifyUser ) ) { if( !NotifyUser.bWrite( gszLocalPrintNotification, _bNotifyLocalPrintedJobs ) || !NotifyUser.bWrite( gszNetworkPrintNotification, _bNotifyNetworkPrintedJobs ) ) { iStatus = kStatusCannotSaveUserNotification; break; } }
//
// If the current user is not administrator, we just return
//
if( !_pServerData->bAdministrator() ) { iStatus = kStatusSuccess; break; }
hr DBGCHK = Data.Set( SPLREG_DEFAULT_SPOOL_DIRECTORY, _strSpoolDirectory );
if( FAILED( hr ) ) { iStatus = kStatusInvalidSpoolDirectory; } else { if( SUCCEEDED( hr ) ) { hr DBGCHK = Data.Set( SPLREG_BEEP_ENABLED, _bBeepErrorJobs ); }
if( SUCCEEDED( hr ) ) { hr DBGCHK = Data.Set( SPLREG_EVENT_LOG, _bEventLogging ); }
if( SUCCEEDED( hr ) ) { hr DBGCHK = Data.Set( SPLREG_NET_POPUP, _bNotifyPrintedJobs ); }
if( SUCCEEDED( hr ) && _bNewOptionSupport ) { hr DBGCHK = Data.Set( SPLREG_NET_POPUP_TO_COMPUTER, _bNotifyPrintedJobsComputer ); }
if( SUCCEEDED( hr ) ) { iStatus = kStatusSuccess;
if( HRESULT_CODE( hr ) == ERROR_SUCCESS_RESTART_REQUIRED ) { _pServerData->_bRebootRequired = TRUE; } } else { iStatus = kStatusError; } }
break;
//
// Load defaults from the spooler.
//
case kServerAttributesDefault:
iStatus = kStatusSuccess; break;
//
// Default is to return an error.
//
default:
iStatus = kStatusError; break; }
return iStatus;
}
/*++
Routine Name:
bHandleMessage
Routine Description:
Server property sheet message handler. This handler only handles events it wants and the base class handle will do the standard message handling.
Arguments:
uMsg - Windows message wParam - Word parameter lParam - Long parameter
Return Value:
TRUE if message was handled, FALSE if message not handled.
--*/
BOOL TServerSettings:: bHandleMessage( IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ) { BOOL bStatus = FALSE; BOOL bChanged = FALSE;
switch( uMsg ){
case WM_COMMAND:
//
// Monitor changes in the UI to highlight the apply button.
//
switch( GET_WM_COMMAND_ID( wParam, lParam ) ) {
case IDC_SERVER_SPOOL_DIRECTORY: bChanged = GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE; bStatus = TRUE; break;
case IDC_SERVER_REMOTE_JOB_ERRORS: case IDC_SERVER_LOCAL_JOB_NOTIFY: case IDC_SERVER_NETWORK_JOB_NOTIFY: case IDC_SERVER_JOB_NOTIFY: case IDC_SERVER_JOB_NOTIFY_COMPUTER: case IDC_SERVER_EVENT_LOGGING_ERROR: case IDC_SERVER_EVENT_LOGGING_WARN: case IDC_SERVER_EVENT_LOGGING_INFO: { if( IDC_SERVER_JOB_NOTIFY == GET_WM_COMMAND_ID( wParam, lParam ) ) { vEnableCtl( _hDlg, IDC_SERVER_JOB_NOTIFY_COMPUTER, bGetCheck( _hDlg, IDC_SERVER_JOB_NOTIFY ) ); }
bChanged = TRUE; bStatus = TRUE; } break;
default: bStatus = FALSE; break; } break;
default: bStatus = FALSE; break; }
//
// If something changed enable the apply button.
//
if( bChanged ){ _bChanged = TRUE; PropSheet_Changed( GetParent( _hDlg ), _hDlg ); }
//
// If the message was not handled let the base class handle it.
//
if( bStatus == FALSE ) bStatus = TServerProp::bHandleMessage( uMsg, wParam, lParam );
return bStatus; }
/********************************************************************
Port selection.
********************************************************************/ TServerPorts:: TServerPorts( IN TServerData *pServerData ) : TServerProp( pServerData ) { }
TServerPorts:: ~TServerPorts( VOID ) { }
BOOL TServerPorts:: bValid( VOID ) { return ( TServerProp::bValid() && _PortsLV.bValid() ); }
BOOL TServerPorts:: bReadUI( VOID ) { return TRUE; }
BOOL TServerPorts:: bSaveUI( VOID ) { return TRUE; }
/*++
Routine Name:
bSetUI
Routine Description:
Loads the property sheet dialog with the document data information.
Arguments:
None.
Return Value:
TRUE if data loaded successfully, FALSE if error occurred.
--*/ BOOL TServerPorts:: bSetUI( VOID ) { //
// Set the printer title.
//
if( !bSetEditText( _hDlg, IDC_SERVER_NAME, _pServerData->strMachineName() )) { vShowUnexpectedError( _pServerData->hwnd(), IDS_SERVER_PROPERTIES_TITLE ); return FALSE; }
//
// Initialize the ports listview.
//
if( !_PortsLV.bSetUI( GetDlgItem( _hDlg, IDC_PORTS ), FALSE, FALSE, TRUE, _hDlg, 0, 0, IDC_PORT_DELETE ) ) { DBGMSG( DBG_WARN, ( "ServerPort.vSetUI: failed %d\n", GetLastError( ))); vShowUnexpectedError( _pServerData->hwnd(), IDS_SERVER_PROPERTIES_TITLE ); return FALSE; }
//
// Load ports into the view.
//
if( !_PortsLV.bReloadPorts( _pServerData->pszServerName() ) ) { DBGMSG( DBG_WARN, ( "ServerPort.vSetUI: bReloadPorts failed %d\n", GetLastError( ))); vShowUnexpectedError( _pServerData->hwnd(), IDS_SERVER_PROPERTIES_TITLE ); return FALSE; }
//
// Select the first item
//
_PortsLV.vSelectItem( 0 );
//
// Adding / deleting / configuring ports is not supported on remote downlevel machines.
//
if( !_pServerData->bAdministrator() || _pServerData->bRemoteDownLevel() ) { //
// Disable things if not administrator.
//
vEnableCtl( _hDlg, IDC_PORT_CREATE, FALSE ); vEnableCtl( _hDlg, IDC_PORT_DELETE, FALSE ); vEnableCtl( _hDlg, IDC_PROPERTIES, FALSE ); }
//
// Bidi support is currently disabled.
//
ShowWindow( GetDlgItem( _hDlg, IDC_ENABLE_BIDI ), SW_HIDE );
return TRUE;
}
/*++
Routine Name:
bHandleMessage
Routine Description:
Server property sheet message handler. This handler only handles events it wants and the base class handle will do the standard message handling.
Arguments:
uMsg - Windows message wParam - Word parameter lParam - Long parameter
Return Value:
TRUE if message was handled, FALSE if message not handled.
--*/ BOOL TServerPorts:: bHandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam ) { BOOL bStatus = FALSE;
switch( uMsg ){
case WM_COMMAND: switch( GET_WM_COMMAND_ID( wParam, lParam ) ){
case IDC_PORT_DELETE: { //
// Delete the selected port.
//
HWND hwnd = GetDlgItem( _hDlg, IDC_PORT_DELETE );
//
// We will only delete the port if the button is enabled, this check is
// necessary if the user uses the delete key on the keyboard to delete
// the port.
//
if( IsWindowEnabled( hwnd ) ) { bStatus = _PortsLV.bDeletePorts( _hDlg, _pServerData->pszServerName( ));
if( bStatus ) { SetFocus( hwnd ); } } } break;
case IDC_PROPERTIES:
//
// Configure the selected port.
//
bStatus = _PortsLV.bConfigurePort( _hDlg, _pServerData->pszServerName( )); SetFocus( GetDlgItem( _hDlg, IDC_PROPERTIES ) ); break;
case IDC_PORT_CREATE: { //
// Create add ports class.
//
TAddPort AddPort( _hDlg, _pServerData->pszServerName(), TRUE );
//
// Insure the add port was created successfully.
//
bStatus = VALID_OBJ( AddPort );
if( !bStatus ) {
vShowUnexpectedError( _hDlg, TAddPort::kErrorMessage );
} else {
//
// Interact with the Add Ports dialog.
//
bStatus = AddPort.bDoModal();
if( bStatus ){
//
// Load the machine's ports into the listview.
//
bStatus = _PortsLV.bReloadPorts( _pServerData->pszServerName( ), TRUE ); } } } break;
default: bStatus = FALSE; break; }
break;
case WM_NOTIFY:
//
// Handle any ports list view messages.
//
switch( wParam ) { case IDC_PORTS:
//
// Enable/disable buttons depending on the current status
//
if( _pServerData->bAdministrator() && ( ((LPNMHDR)lParam)->code == LVN_ITEMCHANGED ) ) { if( _pServerData->bRemoteDownLevel() ) { // remote or downlevel case - all buttons will be disabled
vEnableCtl( _hDlg, IDC_PORT_CREATE, FALSE ); vEnableCtl( _hDlg, IDC_PORT_DELETE, FALSE ); vEnableCtl( _hDlg, IDC_PROPERTIES, FALSE ); } else if( 0 == _PortsLV.cSelectedItems() ) { // no selection case. disable config & delete buttons
vEnableCtl( _hDlg, IDC_PORT_CREATE, TRUE ); vEnableCtl( _hDlg, IDC_PORT_DELETE, FALSE ); vEnableCtl( _hDlg, IDC_PROPERTIES, FALSE ); } else if( 1 == _PortsLV.cSelectedItems() ) { // only one port is selected - enable all buttons
vEnableCtl( _hDlg, IDC_PORT_CREATE, TRUE ); vEnableCtl( _hDlg, IDC_PORT_DELETE, TRUE ); vEnableCtl( _hDlg, IDC_PROPERTIES, TRUE ); } else { // many ports are selected and we are not in remote and/or downlevel case
// enable only the create and delete buttons
vEnableCtl( _hDlg, IDC_PORT_CREATE, TRUE ); vEnableCtl( _hDlg, IDC_PORT_DELETE, TRUE ); vEnableCtl( _hDlg, IDC_PROPERTIES, FALSE ); } }
(VOID)_PortsLV.bHandleNotifyMessage( lParam );
bStatus = FALSE; break;
default: bStatus = FALSE; break; } break;
default: bStatus = FALSE; break;
}
//
// If the message was handled.
//
if( bStatus != FALSE ) { vCancelToClose( _hDlg ); return bStatus; }
//
// If the message was not handled pass it on to the base class.
//
if( bStatus == FALSE ) bStatus = TServerProp::bHandleMessage( uMsg, wParam, lParam );
return bStatus;
}
/********************************************************************
Server Driver Administration.
********************************************************************/ TServerDrivers:: TServerDrivers( IN TServerData *pServerData ) : TServerProp( pServerData ), _bChanged( FALSE ), _bCanRemoveDrivers( TRUE ) { }
TServerDrivers:: ~TServerDrivers( VOID ) { }
BOOL TServerDrivers:: bValid( VOID ) { return TServerProp::bValid() && VALID_OBJ( _DriversLV ); }
BOOL TServerDrivers:: bReadUI( VOID ) { return TRUE; }
/*++
Routine Name:
bSaveUI
Routine Description:
Save the contenst of the UI to the system.
Arguments:
None.
Return Value:
TRUE if save was successful, FALSE if error occurred.
--*/ BOOL TServerDrivers:: bSaveUI( VOID ) { //
// Display the hour glass the refresh may take awhile.
//
TWaitCursor Cur;
//
// Create a driver noitfy.
//
TServerDriverNotify Notify ( this );
//
// Install / Remove / Update any drivers.
//
(VOID)_DriversLV.bSendDriverInfoNotification( Notify );
//
// Refesh the drivers list.
//
TStatusB bStatus; bStatus DBGCHK = _DriversLV.bRefresh(); if( !bStatus ) { //
// Display the error message.
//
iMessage( _hDlg, IDS_SERVER_PROPERTIES_TITLE, IDS_ERR_DRIVERS_NOT_REFRESHED, MB_OK|MB_ICONSTOP, kMsgGetLastError, NULL ); }
//
// Sort the environment column.
//
(VOID)_DriversLV.bSortColumn( TDriversLV::kEnvironmentColumn );
//
// Sort the driver name.
//
(VOID)_DriversLV.bSortColumn( TDriversLV::kDriverNameColumn );
//
// Select the first item in the list view.
//
_DriversLV.vSelectItem( 0 );
//
// Return success only if there was not a falure and the refresh succeeded.
//
return bStatus; }
/*++
Routine Name:
bSetUI
Routine Description:
Loads the property sheet dialog with the document data information.
Arguments:
None.
Return Value:
TRUE if data loaded successfully, FALSE if error occurred.
--*/ BOOL TServerDrivers:: bSetUI( VOID ) { TStatusB bStatus;
//
// Set the printer title.
//
bStatus DBGCHK = bSetEditText( _hDlg, IDC_SERVER_NAME, _pServerData->strMachineName() );
//
// If we are an administrator handle the delete message.
//
UINT idRemove = _pServerData->bAdministrator() ? IDC_REMOVE_DRIVER : 0;
//
// Set the drivers list view.
//
bStatus DBGCHK = _DriversLV.bSetUI( _pServerData->pszServerName(), _hDlg, IDC_MORE_DETAILS, IDC_ITEM_SELECTED, idRemove );
//
// Load the list view with driver data.
//
bStatus DBGCHK = _DriversLV.bRefresh();
//
// Set the default sort order.
//
bStatus DBGCHK = _DriversLV.bSortColumn( TDriversLV::kEnvironmentColumn );
//
// Sort the driver name.
//
bStatus DBGCHK = _DriversLV.bSortColumn( TDriversLV::kDriverNameColumn );
//
// Update the button state.
//
vUpdateButtons();
//
// Select the first item in the list view.
//
_DriversLV.vSelectItem( 0 );
//
// If we are talking to a down level spooler then deleting printer drivers
// can only be done with a call to DeletePrinterDriver, no ex version exists.
// Because DeletePrinterDriver only allows the caller to delete all drivers
// of a specific environment with out regards to version, we have decided to
// not allow removing printer drivers on down level machines. In addition
// DeletePrinterDriver is as kind of broken since it does not actually remove
// the driver files, it only removes the registry entries.
//
if( GetDriverVersion( _pServerData->dwDriverVersion() ) <= 2 ) { _bCanRemoveDrivers = FALSE; }
return bStatus; }
/*++
Routine Name:
vUpdateButtons
Routine Description:
Update the dialog buttons.
Arguments:
None.
Return Value:
Nothing.
--*/ VOID TServerDrivers:: vUpdateButtons( VOID ) { //
// Default is the details button disabled.
//
vEnableCtl( _hDlg, IDC_MORE_DETAILS, FALSE ); vEnableCtl( _hDlg, IDC_UPDATE_DRIVER, FALSE ); vEnableCtl( _hDlg, IDC_REMOVE_DRIVER, FALSE );
//
// If not an administrator then disable the add button.
//
if( !_pServerData->bAdministrator() ) { vEnableCtl( _hDlg, IDC_ADD_DRIVER, FALSE ); } }
/*++
Routine Name:
bHandleMessage
Routine Description:
Server property sheet message handler. This handler only handles events it wants and the base class handle will do the standard message handling.
Arguments:
uMsg - Windows message wParam - Word parameter lParam - Long parameter
Return Value:
TRUE if message was handled, FALSE if message not handled.
--*/ BOOL TServerDrivers:: bHandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam ) { BOOL bStatus = TRUE; BOOL bChanged = FALSE;
switch( uMsg ) { case WM_COMMAND: switch( GET_WM_COMMAND_ID( wParam, lParam ) ) { case IDC_ADD_DRIVER: if( bHandleAddDriver( uMsg, wParam, lParam ) ) bChanged = TRUE; break;
case IDC_UPDATE_DRIVER: if( bHandleUpdateDriver( uMsg, wParam, lParam ) ) bChanged = TRUE; break;
case IDC_REMOVE_DRIVER: if( bHandleRemoveDriver( uMsg, wParam, lParam ) ) bChanged = TRUE; break;
case IDC_MORE_DETAILS: bHandleDriverDetails( uMsg, wParam, lParam ); break;
case IDC_ITEM_SELECTED: bHandleDriverItemSelection( uMsg, wParam, lParam ); break;
default: bStatus = FALSE; break;
} break;
default: bStatus = FALSE; break; }
//
// If something changed save the changes and change the
// the ok button to close and gray the cancel button.
//
if( bChanged ){
//
// Update the button state.
//
vUpdateButtons();
//
// Save the UI and convert CancelToClose
//
(VOID)bSaveUI(); vCancelToClose( _hDlg ); }
//
// Let the list view handle their message.
//
if( bStatus == FALSE ) bStatus = _DriversLV.bHandleMessage( uMsg, wParam, lParam );
//
// If the message was not handled pass it on to the base class.
//
if( bStatus == FALSE ) bStatus = TServerProp::bHandleMessage( uMsg, wParam, lParam );
return bStatus;
}
BOOL TServerDrivers:: bHandleDriverItemSelection( UINT uMsg, WPARAM wParam, LPARAM lParam ) { DBGMSG( DBG_TRACE, ( "TServerDrivers::bHandleDriverItemSelection\n" ) );
//
// Get the button state in a local variable.
//
BOOL bButtonState = _DriversLV.bIsAnyItemSelcted();
//
// If any item is selected then enable the properties button.
//
vEnableCtl( _hDlg, IDC_MORE_DETAILS, bButtonState ); vEnableCtl( _hDlg, IDC_UPDATE_DRIVER, bButtonState && _pServerData->bAdministrator() ); vEnableCtl( _hDlg, IDC_REMOVE_DRIVER, bButtonState && _pServerData->bAdministrator() && _bCanRemoveDrivers );
return TRUE; }
BOOL TServerDrivers:: bHandleAddDriver( UINT uMsg, WPARAM wParam, LPARAM lParam ) { DBGMSG( DBG_TRACE, ( "TServerDrivers::bHandleAddDriver\n" ) );
TString strDriverName; TStatusB bStatus; BOOL bCanceled; UINT nDriverInstallCount = 0;
//
// Add any new drivers, displaying the add driver wizard.
//
bStatus DBGCHK = bInstallNewPrinterDriver( _hDlg, TWizard::kDriverInstall, _pServerData->pszServerName(), strDriverName, NULL, kDriverWizardDefault, &bCanceled, FALSE, &nDriverInstallCount ); //
// If any driver was installed then return true
// inorder to indicate we need to refresh the driver list view.
//
if( nDriverInstallCount ) { bStatus DBGNOCHK = TRUE; }
return bStatus; }
BOOL TServerDrivers:: bHandleRemoveDriver( UINT uMsg, WPARAM wParam, LPARAM lParam ) { DBGMSG( DBG_TRACE, ( "TServerDrivers::bHandleRemoveDriver\n" ) );
//
// If we cannot remove the drivers because we are administrating
// a downlevel machine then do nothing.
//
if( !_bCanRemoveDrivers ) { return FALSE; }
TStatusB bStatus;
//
// Get a list of the selected items.
//
UINT nCount = 0; TDriverTransfer DriverTransfer; bStatus DBGCHK = _DriversLV.bGetSelectedDriverInfo( DriverTransfer, &nCount );
DBGMSG( DBG_TRACE, ( "Selected count %d\n", nCount ) );
//
// Warn the user that they are about to delete a driver
// from the system permently.
//
if( bStatus && nCount ) { bStatus DBGNOCHK = bWarnUserDriverDeletion( DriverTransfer.DriverInfoList_pGetByIndex( 0 ), nCount ); }
//
// Delete the driver if the count is non zero.
//
if( bStatus && nCount ) { //
// Initialize the list iterator.
//
TIter Iter; DriverTransfer.DriverInfoList_vIterInit( Iter );
TDriverInfo *pDriverInfo;
for( Iter.vNext(); Iter.bValid(); ) { pDriverInfo = DriverTransfer.DriverInfoList_pConvert( Iter ); Iter.vNext();
DBGMSG( DBG_TRACE, ( "Selected Driver Name: "TSTR"\n", (LPCTSTR)pDriverInfo->strName() ) );
//
// If the driver was added but not installed then
// removed it the item entirely.
//
if( pDriverInfo->vGetInfoState() == TDriverInfo::kAdd ) { DBGMSG( DBG_TRACE, ( "Uninstalled driver was removed.\n" ) ); pDriverInfo->vSetInfoState( TDriverInfo::kRemoved ); }
//
// Mark the item to be removed.
//
else { DBGMSG( DBG_TRACE, ( "Driver removed.\n" ) ); pDriverInfo->vSetInfoState( TDriverInfo::kRemove ); } } //
// Return the removed items back to the list and delete
// these items form the UI part of the list view.
//
_DriversLV.vDeleteDriverInfoFromListView( DriverTransfer ); } else { //
// Return the selected items back to the list view.
//
_DriversLV.vReturnDriverInfoToListView( DriverTransfer ); }
//
// If there are no more drivers in the list view then remove
// default button state from the remove button and change it
// to the add button, since the add button is always enabled.
//
if( !_DriversLV.uGetListViewItemCount() ) { SendMessage( GetDlgItem( _hDlg, IDC_REMOVE_DRIVER ), BM_SETSTYLE, MAKEWPARAM( BS_PUSHBUTTON, 0 ), MAKELPARAM( TRUE, 0 ) );
SendMessage( GetDlgItem( _hDlg, IDC_ADD_DRIVER ), BM_SETSTYLE, MAKEWPARAM( BS_DEFPUSHBUTTON, 0 ), MAKELPARAM( TRUE, 0 ) );
SetFocus( GetDlgItem( _hDlg, IDC_ADD_DRIVER ) ); }
return bStatus; }
BOOL TServerDrivers:: bHandleUpdateDriver( UINT uMsg, WPARAM wParam, LPARAM lParam ) { DBGMSG( DBG_TRACE, ( "TServerDrivers::bHandleUpdateDriver\n" ) );
TStatusB bStatus; bStatus DBGNOCHK = FALSE;
//
// Get a list of the selected items.
//
UINT nCount = 0; TDriverTransfer DriverTransfer; bStatus DBGCHK = _DriversLV.bGetSelectedDriverInfo( DriverTransfer, &nCount );
DBGMSG( DBG_TRACE, ( "Selected count %d\n", nCount ) );
//
// Warn the user that they are about to update a driver from the system permently.
//
if( bStatus && nCount ) { bStatus DBGNOCHK = bWarnUserDriverUpdate( DriverTransfer.DriverInfoList_pGetByIndex( 0 ), nCount ); }
//
// Delete the driver if the count is non zero.
//
if( bStatus && nCount ) { //
// Initialize the list iterator.
//
TIter Iter; DriverTransfer.DriverInfoList_vIterInit( Iter );
TDriverInfo *pDriverInfo;
for( Iter.vNext(); Iter.bValid(); Iter.vNext() ) { pDriverInfo = DriverTransfer.DriverInfoList_pConvert( Iter );
DBGMSG( DBG_TRACE, ( "Selected Driver Name: "TSTR"\n", (LPCTSTR)pDriverInfo->strName() ) );
//
// Mark all the selected driver as update canidates.
//
pDriverInfo->vSetInfoState( TDriverInfo::kUpdate ); } }
//
// Return the selected items back to the list view.
//
_DriversLV.vReturnDriverInfoToListView( DriverTransfer );
return bStatus; }
BOOL TServerDrivers:: bHandleDriverDetails( UINT uMsg, WPARAM wParam, LPARAM lParam ) { DBGMSG( DBG_TRACE, ( "TServerDrivers::bHandleDetails\n" ) );
TStatusB bStatus; TDriverInfo *pDriverInfo; TDriversLV::THandle Handle;
for( bStatus DBGNOCHK = TRUE; bStatus ; ) { bStatus DBGNOCHK = _DriversLV.bGetSelectedDriverInfo( &pDriverInfo, Handle );
if( bStatus ) { TDriverDetails Details( _hDlg, pDriverInfo );
if( VALID_OBJ( Details ) ) { Details.bDoModal(); } } }
return TRUE; }
BOOL TServerDrivers:: bWarnUserDriverDeletion( IN TDriverInfo *pDriverInfo, IN UINT nCount ) const { //
// If there are multiple items selected then the warning message
// is changed.
//
INT iMsg = nCount == 1 ? IDS_ERR_DELETE_PRINTER_DRIVER : IDS_ERR_DELETE_PRINTER_DRIVERN;
//
// Return success of the user was warned and decided to complete
// the printer driver removal.
//
return iMessage( _hDlg, IDS_SERVER_PROPERTIES_TITLE, iMsg, MB_YESNO | MB_ICONQUESTION, kMsgNone, NULL, static_cast<LPCTSTR>( pDriverInfo->strName() ) ) == IDYES ? TRUE : FALSE; }
BOOL TServerDrivers:: bWarnUserDriverUpdate( IN TDriverInfo *pDriverInfo, IN UINT nCount ) const { //
// If there are multiple items selected then the warning message
// is changed.
//
INT iMsg = nCount == 1 ? IDS_ERR_UPDATE_PRINTER_DRIVER : IDS_ERR_UPDATE_PRINTER_DRIVERN;
//
// Return success of the user was warned and decided to complete
// the printer driver removal.
//
return iMessage( _hDlg, IDS_SERVER_PROPERTIES_TITLE, iMsg, MB_YESNO | MB_ICONQUESTION, kMsgNone, NULL, static_cast<LPCTSTR>( pDriverInfo->strName() ) ) == IDYES ? TRUE : FALSE; }
/********************************************************************
Server Driver Notify
********************************************************************/ TServerDriverNotify:: TServerDriverNotify( TServerDrivers *pServerDrivers ) : _pServerDrivers( pServerDrivers ), _pDi( NULL ), _uNotifyCount( 0 ), _bActionFailed( FALSE ) { }
TServerDriverNotify:: ~TServerDriverNotify( VOID ) { //
// Ensure we release the printer driver installation object.
//
delete _pDi; }
/*++
Routine Name:
bNotify
Routine Description:
Called for all driver info classes in the list view.
Arguments:
pDriverInfo - Pointer to driver info class.
Return Value:
TRUE continue for the remaing driver info classes. FALSE stop notification.
--*/ BOOL TServerDriverNotify:: bNotify( IN TDriverInfo *pDriverInfo ) { DBGMSG( DBG_TRACE, ( "TServerDriverNotify::bNotify\n" ) );
//
// Adjust the notify count, used for detection the multi selection
//
//
_uNotifyCount++;
BOOL bStatus = TRUE; INT iMessageId = 0;
switch( pDriverInfo->vGetInfoState() ) { case TDriverInfo::kRemove: bStatus = bRemove( pDriverInfo ); iMessageId = IDS_ERR_ALL_DRIVER_NOT_REMOVED; break;
case TDriverInfo::kAdd: bStatus = bInstall( pDriverInfo ); iMessageId = IDS_ERR_ALL_DRIVER_NOT_INSTALLED; break;
case TDriverInfo::kUpdate: bStatus = bUpdate( pDriverInfo ); iMessageId = IDS_ERR_ALL_DRIVER_NOT_UPDATED; break;
default: bStatus = TRUE; iMessageId = 0; break; }
if( !bStatus ) { if( iMessageId && GetLastError() != ERROR_CANCELLED ) { //
// Display the error message.
//
iMessage( _pServerDrivers->_hDlg, IDS_SERVER_PROPERTIES_TITLE, iMessageId, MB_OK|MB_ICONSTOP, kMsgGetLastError, NULL, static_cast<LPCTSTR>( pDriverInfo->strName() ), static_cast<LPCTSTR>( pDriverInfo->strEnvironment() ), static_cast<LPCTSTR>( pDriverInfo->strVersion() ) ); }
_bActionFailed = TRUE;
//
// Currently we continue if an error occurred.
//
bStatus = TRUE; }
return bStatus; }
BOOL TServerDriverNotify:: bInstall( IN TDriverInfo *pDriverInfo ) { DBGMSG( DBG_TRACE, ( "TServerDriverNotify::bInstall\n" ) ); SPLASSERT( FALSE ); return TRUE; }
BOOL TServerDriverNotify:: bRemove( IN TDriverInfo *pDriverInfo ) { DBGMSG( DBG_TRACE, ( "TServerDriverNotify::bRemove\n" ) );
TStatusB bStatus; bStatus DBGNOCHK = TRUE;
//
// Delete the specfied printer driver.
//
bStatus DBGCHK = DeletePrinterDriverEx( (LPTSTR)_pServerDrivers->_pServerData->pszServerName(), (LPTSTR)(LPCTSTR)pDriverInfo->strEnv(), (LPTSTR)(LPCTSTR)pDriverInfo->strName(), DPD_DELETE_UNUSED_FILES|DPD_DELETE_SPECIFIC_VERSION, pDriverInfo->dwVersion());
//
// If we are trying this action on a down level spooler.
//
if( !bStatus && GetLastError() == RPC_S_PROCNUM_OUT_OF_RANGE ) { bStatus DBGCHK = DeletePrinterDriver( (LPTSTR)_pServerDrivers->_pServerData->pszServerName(), (LPTSTR)(LPCTSTR)pDriverInfo->strEnv(), (LPTSTR)(LPCTSTR)pDriverInfo->strName() ); }
//
// If the driver was deleted then mark the driver structure as removed.
//
if( bStatus ) { pDriverInfo->vSetInfoState( TDriverInfo::kRemoved ); } return bStatus; }
BOOL TServerDriverNotify:: bUpdate( IN TDriverInfo *pDriverInfo ) { DBGMSG( DBG_TRACE, ( "TServerDriverNotify::bUpdate\n" ) );
TStatusB bStatus; DWORD dwEncode = 0; DWORD dwPrevInstallFlags = 0;
bStatus DBGNOCHK = TRUE;
//
// Lazy load the printer drivers installation class.
//
if( !_pDi ) { _pDi = new TPrinterDriverInstallation( _pServerDrivers->_pServerData->pszServerName(), _pServerDrivers->_hDlg );
bStatus DBGNOCHK = VALID_PTR( _pDi ); }
if( bStatus ) { DBGMSG( DBG_TRACE, ( "Installing driver "TSTR"\n", (LPCTSTR)pDriverInfo->_strName ) );
//
// Encode the printer driver architercure and version
//
bStatus DBGCHK = bEncodeArchVersion( pDriverInfo->_strEnv, pDriverInfo->_dwVersion, &dwEncode );
//
// Get the current install flags.
//
dwPrevInstallFlags = _pDi->GetInstallFlags();
//
// We do not copy the inf for version 2 drivers.
//
if( GetDriverVersion( dwEncode ) == 2 ) { //
// We don't copy the inf for version 2 drivers.
//
_pDi->SetInstallFlags( DRVINST_DONOTCOPY_INF); }
//
// On NT5 and greater we can overwrite all the driver files,
// however on less than NT5 we can only copy newer files.
//
DWORD dwAddPrinterDriverFlags = APD_COPY_ALL_FILES; DWORD dwCurrentDriverEncode = 0;
if( _pDi->bGetCurrentDriverEncode( &dwCurrentDriverEncode ) ) { if( GetDriverVersion( dwCurrentDriverEncode ) <= 2 ) { dwAddPrinterDriverFlags = APD_COPY_NEW_FILES; } }
//
// Select and install the printer driver.
//
BOOL bOfferReplacementDriver = FALSE; dwAddPrinterDriverFlags |= APD_INSTALL_WARNED_DRIVER; bStatus DBGCHK = _pDi->bSetDriverName( pDriverInfo->_strName ) && _pDi->bInstallDriver( &pDriverInfo->_strName, bOfferReplacementDriver, FALSE, _pServerDrivers->_hDlg, dwEncode, dwAddPrinterDriverFlags, TRUE );
if( bStatus ) { //
// Indicate this driver has been installed.
//
pDriverInfo->vSetInfoState( TDriverInfo::kInstalled ); }
//
// Restore the previous install flags.
//
_pDi->SetInstallFlags( dwPrevInstallFlags ); }
return bStatus; }
/********************************************************************
Server property windows.
********************************************************************/ TServerWindows:: TServerWindows( IN TServerData *pServerData ) : _pServerData( pServerData ), _Forms( pServerData ), _Ports( pServerData ), _Settings( pServerData ), _Drivers( pServerData ) { }
TServerWindows:: ~TServerWindows( ) { }
/*++
Routine Name:
bBuildPages
Routine Description:
Builds the document property windows.
Arguments:
None - class specific.
Return Value:
TRUE pages built ok, FALSE failure building pages.
--*/ BOOL TServerWindows:: bBuildPages( VOID ) {
DBGMSG( DBG_TRACE, ( "TServerWindows bBuildPages\n") );
struct SheetInitializer { MGenericProp *pSheet; INT iDialog; };
SheetInitializer aSheetInit[] = { {&_Forms, DLG_FORMS }, {&_Ports, DLG_SERVER_PORTS }, {&_Drivers, DLG_SERVER_DRIVERS }, {&_Settings, DLG_SERVER_SETTINGS }, {NULL, NULL, } };
BOOL bReturn = FALSE; BOOL bSheetsDestroyed = FALSE; PROPSHEETHEADER psh; HPROPSHEETPAGE ahpsp[COUNTOF( aSheetInit )]; PROPSHEETPAGE psp;
ZeroMemory( &psp, sizeof( psp )); ZeroMemory( &psh, sizeof( psh )); ZeroMemory( ahpsp, sizeof( ahpsp ));
psh.dwSize = sizeof( psh ); psh.hwndParent = _pServerData->hwnd(); psh.dwFlags = PSH_USEHICON | PSH_PROPTITLE; psh.phpage = ahpsp; psh.hIcon = _pServerData->hDefaultSmallIcon(); psh.nStartPage = _pServerData->uStartPage(); psh.hInstance = ghInst; psh.pszCaption = (LPCTSTR)_pServerData->strTitle(); psh.nPages = COUNTOF( ahpsp );
psp.dwSize = sizeof( psp ); psp.hInstance = ghInst; psp.pfnDlgProc = MGenericProp::SetupDlgProc;
//
// Create the property sheets.
//
for( UINT i = 0; i < COUNTOF( ahpsp ); ++i ){ psp.pszTemplate = MAKEINTRESOURCE( aSheetInit[i].iDialog ); psp.lParam = (LPARAM)(MGenericProp*)aSheetInit[i].pSheet; ahpsp[i] = CreatePropertySheetPage( &psp ); }
//
// Insure the index matches the number of pages.
//
SPLASSERT( i == psh.nPages );
//
// Verify all pages were created.
//
for( i = 0; i < COUNTOF( ahpsp ); ++i ){ if( !ahpsp[i] ){ DBGMSG( DBG_WARN, ( "Server Property sheet Unable to create page %d\n", i )); goto Done; } }
//
// Indicate we do not have to distory the property sheets.
//
bSheetsDestroyed = TRUE;
//
// Display the property sheets.
//
if( PropertySheet( &psh ) < 0 ){
DBGMSG( DBG_WARN, ( "Server Property Sheet failed %d\n", GetLastError())); vShowResourceError( _pServerData->hwnd() );
} else {
//
// Check if the reboot flag was returned.
//
if( _pServerData->_bRebootRequired ) {
//
// Display message, reboot neccessary.
//
if (_pServerData->pszServerName()) {
//
// if the server name is not NULL, we assume it is a remote printers folder.
// This is not true if user opens the local printers folder from
// \\local-machine-name, but this is a rare case that we can ignore.
//
iMessage( _pServerData->hwnd(), IDS_SERVER_PROPERTIES_TITLE, IDS_SERVER_SETTINGS_CHANGED_REMOTE, MB_ICONEXCLAMATION, kMsgNone, NULL, _pServerData->pszServerName() ); } else {
iMessage( _pServerData->hwnd(), IDS_SERVER_PROPERTIES_TITLE, IDS_SERVER_SETTINGS_CHANGED, MB_ICONEXCLAMATION, kMsgNone, NULL ); } }
bReturn = TRUE;
}
Done:
//
// If Sheets weren't destoryed, do it now.
//
if( !bSheetsDestroyed ){
for( i = 0; i < COUNTOF( ahpsp ); ++i ){ if( ahpsp[i] ){ DestroyPropertySheetPage( ahpsp[i] ); } } }
return bReturn; }
/*++
Routine Name:
bDisplayPages
Routine Description:
Displays the document property pages.
Arguments:
None.
Return Value:
TRUE if pages were displayed, FALSE
--*/ BOOL TServerWindows:: bDisplayPages( VOID ) { return TRUE; }
/*++
Routine Name:
bValid
Routine Description:
Returns if class and its dat members are vaild.
Arguments:
None.
Return Value:
TRUE - class is valid, FALSE class is invalid.
--*/
BOOL TServerWindows:: bValid( VOID ) { //
// Validated all the known pages.
//
if( VALID_OBJ( _Forms ) && VALID_OBJ( _Ports ) && VALID_OBJ( _Drivers ) && VALID_OBJ( _Settings ) ){
return TRUE; }
return FALSE;
}
|