mirror of https://github.com/tongzx/nt5src
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
3522 lines
76 KiB
/*++
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|