|
|
/*++
Copyright (C) Microsoft Corporation, 1996 - 1999 All rights reserved.
Module Name:
rundll.cxx
Abstract:
Run dll entry interface for lauching printer related UI from shell extenstion and other shell related components.
Author:
Steve Kiraly (SteveKi) 29-Sept-1996
Revision History:
--*/ #include "precomp.hxx"
#pragma hdrstop
#include "rundll.hxx"
#include "getopt.hxx"
#include "parser.hxx"
#include "permc.hxx"
#include "asyncdlg.hxx"
#include "tstpage.hxx"
#include "time.hxx"
#include "psetup.hxx"
#include "drvsetup.hxx"
#include "instarch.hxx"
#include "portslv.hxx"
#include "dsinterf.hxx"
#include "prtprop.hxx"
#include "prtshare.hxx"
#include "dsinterf.hxx"
#include "drvsetup.hxx"
#include "driverif.hxx"
#include "driverlv.hxx"
#include "archlv.hxx"
#include "detect.hxx"
#include "setup.hxx"
#include "spllibex.hxx"
#include "spinterf.hxx"
/*++
Routine Name:
PrintUIEntryW
Routine Description:
Interface for the Rundll32 process.
Arguments:
hwnd - Window handle of stub window. hInstance, - Rundll instance handle. pszCmdLine - Pointer to UNICOE command line. nCmdShow - Show command value always TRUE.
Return Value:
Nothing.
--*/ DWORD PrintUIEntryW( IN HWND hwnd, IN HINSTANCE hInstance, IN LPCTSTR pszCmdLine, IN UINT nCmdShow ) { DBGMSG( DBG_TRACE, ( "PrintUIEntryW interface\n" ) ); DBGMSG( DBG_TRACE, ( "hwnd %x\n", hwnd ) ); DBGMSG( DBG_TRACE, ( "hInstance %x\n", hInstance ) ); DBGMSG( DBG_TRACE, ( "pszCmdLine %ws\n", pszCmdLine ) ); DBGMSG( DBG_TRACE, ( "nCmdShow %d\n", nCmdShow ) ); DBGMSG( DBG_TRACE, ( "CommandLine %ws\n", GetCommandLine() ) );
//
// we need to count the error messages to see if necessary to
// show up UI in case of an error or if somebody has been done
// this already
//
CMsgBoxCounter msgCounter(MB_ICONSTOP|MB_ICONINFORMATION);
UINT ac = 0; TCHAR **av = NULL; BOOL bRetval = FALSE; AParams Params = {0};
//
// Strip any trailing white space.
//
vStripTrailWhiteSpace( (LPTSTR)pszCmdLine );
//
// Convert the command line to an argv,
//
bRetval = StringToArgv( pszCmdLine, // Command line arguments
&ac, // Place to return arg count
&av, // Place to return argv
FALSE ); // There is no file name on the command line
if( bRetval ) { //
// Store pointer to command line.
//
Params.pszCmdLine = pszCmdLine;
//
// Parse the command line argumens and execute the command.
//
bRetval = bDoCommand( hwnd, ac, av, &Params ); }
if( !bRetval ) { //
// If we are not in quiet mode display error messsage.
//
if( !Params.Flags.IsQuiet && 0 == msgCounter.GetCount() ) { switch( Params.dwLastError ) { case ERROR_SUCCESS: case ERROR_CANCELLED: break;
case ERROR_ACCESS_DENIED: { // show up a friendly message that conform the shell32.dll
// message in this case. this is because this will be invoked
// primarily from shell32.dll from the runas commands
iMessage(NULL, IDS_PRINTERS_TITLE, IDS_FRIENDLY_ACCESSDENIED, MB_OK|MB_ICONINFORMATION, kMsgNone, NULL); } break;
case ERROR_INVALID_PARAMETER: { // show up a friendly message to say that the arguments are invalid
iMessage(NULL, IDS_PRINTERS_TITLE, IDS_ERROR_INVALID_ARG, MB_OK|MB_ICONSTOP, kMsgNone, NULL); } break;
default: { // we are going to show a generic error message here
iMessage(NULL, IDS_PRINTERS_TITLE, IDS_ERR_GENERIC, MB_OK|MB_ICONSTOP, Params.dwLastError, NULL); } break; }
//
// If the last error code was not set then set it to a generic
// error value. We just chose one, ERROR_INVALID_FUNCTION
//
if( Params.dwLastError == ERROR_SUCCESS ) { Params.dwLastError = GetLastError();
if( Params.dwLastError == ERROR_SUCCESS ) { Params.dwLastError = ERROR_INVALID_FUNCTION; } } } }
//
// Ensure we release the command line argv.
//
ReleaseArgv( av );
//
// If something failed and the error code was not set then set
// the error to an unspecified error value.
//
if( !bRetval ) { //
// Set the last error incase the caller ignores the return value.
//
SetLastError( Params.dwLastError ); }
return Params.dwLastError; }
/*++
Routine Name:
bDoCommand
Routine Description:
Parses the commmand line passed by rundll32.
Arguments:
hwnd - Parent window handle. ac - Number of strings. av - Pointer to an array of pointer to strings.
Return Value:
TRUE function complete ok. FALSE error occurred.
--*/ BOOL bDoCommand( IN HWND hwnd, IN INT ac, IN LPTSTR *av, IN AParams *pParams ) { INT retval; LPTSTR options = TEXT("?KYUPHwuzZkyxqeospS:X:t:d:i:n:r:m:c:l:a:f:b:g:h:v:j:M:W:G:"); // Supported options
INT iFunction = kUnknown; BOOL bStatus = FALSE;
//
// Set to known state
//
SetLastError( ERROR_SUCCESS );
//
// Indicate there is not a file name as the first argument.
//
TGetOptContext context; context.optind = 0;
//
// Process any command line arguments switches.
//
for (context.opterr = 0, retval = 0; retval != EOF; ) { retval = getopt (ac, av, options, context);
switch (retval) { case 't': pParams->dwSheet = _ttoi( context.optarg ); break; case 'n': pParams->pPrinterName = context.optarg; break; case 'r': pParams->pPortName = context.optarg; break; case 'm': pParams->pModelName = context.optarg; break; case 'M': // get the message type first
pParams->uMsgType = *context.optarg == TEXT('q') ? kMsgConfirmation : *context.optarg == TEXT('w') ? kMsgWarning : kMsgUnknownType;
// get the real message text here
context.optarg++; if( kMsgUnknownType != pParams->uMsgType && context.optarg && *context.optarg ) { pParams->pMsgConfirm = context.optarg; } break; case 'b': pParams->pBasePrinterName = context.optarg; break; case 'f': pParams->pInfFileName = context.optarg; break; case 'a': pParams->pBinFileName = context.optarg; break; case 'G': { // global flags
if( *context.optarg == TEXT('w') ) { // we should suppress the setup driver warnings UI
// -- i.e. we're in super quiet mode
pParams->Flags.IsSupressSetupUI = TRUE; } } break; case 'g': iFunction = *context.optarg == TEXT('a') ? kAddPerMachineConnection : *context.optarg == TEXT('d') ? kDeletePerMachineConnection : *context.optarg == TEXT('e') ? kEnumPerMachineConnections : kUnknown; break; case 'j': pParams->pProvider = context.optarg; break; case 'i': iFunction = *context.optarg == TEXT('n') ? kInstallNetPrinter : *context.optarg == TEXT('l') ? kInstallLocalPrinter : *context.optarg == TEXT('d') ? kInstallPrinterDriver : *context.optarg == TEXT('a') ? kInstallDriverWithInf : *context.optarg == TEXT('f') ? kInstallPrinterWithInf : *context.optarg == TEXT('i') ? kInstallLocalPrinterWithInf : kUnknown;
break; case 'd': iFunction = *context.optarg == TEXT('n') ? kDeleteNetPrinter : *context.optarg == TEXT('l') ? kDeleteLocalPrinter : *context.optarg == TEXT('d') ? kDeletePrinterDriver : kUnknown; break; case 'o': iFunction = kWin32QueueView; break; case 's': iFunction = kServerProperties; break; case 'p': iFunction = kProperties; break; case 'X': iFunction = *context.optarg == TEXT('g') ? kPrinterGetSettings : *context.optarg == TEXT('s') ? kPrinterSetSettings : kUnknown; break; case 'e': iFunction = kDocumentDefaults; break; case 'c': pParams->pMachineName = context.optarg; break; case 'l': pParams->pSourcePath = context.optarg; break; case 'h': pParams->pArchitecture = context.optarg; break; case 'v': pParams->pVersion = context.optarg; break; case 'q': pParams->Flags.IsQuiet = TRUE; break; case 'k': iFunction = kPrintTestPage; break; case 'y': iFunction = kSetAsDefault; break; case 'x': pParams->Flags.IsWebPointAndPrint = TRUE; break; case 'z': pParams->Flags.IsNoSharing = TRUE; break; case 'Z': pParams->Flags.IsShared = TRUE; break; case 'u': pParams->Flags.IsUseExistingDriver = TRUE; break; case 'w': pParams->Flags.IsUnknownDriverPrompt = TRUE; break; case 'W': // wizards flags
pParams->Flags.IsWizardRestartable = *context.optarg == TEXT('r') ? TRUE : FALSE; break; case 'H': pParams->Flags.IsHydraSpecific = TRUE; break; case 'P': pParams->Flags.IsPromptForNeededFiles = TRUE; break; case 'Y': pParams->Flags.IsDontAutoGenerateName = TRUE; break; case 'K': pParams->Flags.IsUseNonLocalizedStrings = TRUE; break; case 'S': iFunction = *context.optarg == TEXT('s') ? kPrinterPersist : *context.optarg == TEXT('r') ? kPrinterRestore : kUnknown; break; case 'U': pParams->Flags.IsWindowsUpdate = TRUE; break; case EOF: bStatus = TRUE; break; case '?': iFunction = kCommandHelp; bStatus = TRUE; retval = EOF; break; case INVALID_COMAND: bStatus = FALSE; retval = EOF; break; default: retval = EOF; break; } }
//
// If success validate the command line arguments.
//
if( bStatus ) { //
// Do simple validation on the command line arguments.
//
bStatus = bValidateCommand( iFunction, pParams );
if( bStatus ) { //
// If there are any remaining arguments then get
// the argument count and pointer to it.
//
if( context.optind < ac ) { pParams->av = &av[context.optind]; pParams->ac = ac - context.optind; }
//
// Check to see if we need to ask the user to confirm the operation if
// not in quiet mode.
//
BOOL bContinueExecution = TRUE; if( !pParams->Flags.IsQuiet && kMsgUnknownType != pParams->uMsgType && pParams->pMsgConfirm ) { //
// there is a confirmation/warning message specified and we are going to
// give opportunity to the user to cancel the whole command here
//
UINT uFlags = kMsgConfirmation == pParams->uMsgType ? MB_ICONQUESTION : kMsgConfirmation == pParams->uMsgType ? MB_ICONEXCLAMATION : 0; ASSERT(uFlags); // shouldn't be zero
uFlags |= MB_YESNO; // we are asking YES/NO question
bContinueExecution = (IDYES == iMessage2(NULL, MAKEINTRESOURCE(IDS_PRINTERS_TITLE), pParams->pMsgConfirm, uFlags, kMsgNone, NULL)); }
if( bContinueExecution ) { //
// Execute the command.
//
bStatus = bExecuteCommand( hwnd, iFunction, pParams ); } } }
return bStatus; }
/*++
Routine Name:
bValidateCommand
Routine Description:
Validates the command line arguments
Arguments:
iFunction - Function code. pParams - pointer to paramter structure.
Return Value:
TRUE arguments are valid. FALSE invalid argument found.
--*/ BOOL bValidateCommand( IN INT iFunction, IN AParams *pParams ) { DBGMSG( DBG_TRACE, ("iFunction %d\n", iFunction ) ); DBGMSG( DBG_TRACE, ("Params\n" ) ); DBGMSG( DBG_TRACE, ("Flags %x\n", pParams->Flags ) ); DBGMSG( DBG_TRACE, ("dwSheet %d\n", pParams->dwSheet ) ); DBGMSG( DBG_TRACE, ("dwLastError %d\n", pParams->dwLastError ) ); DBGMSG( DBG_TRACE, ("pPrinterName "TSTR"\n", DBGSTR( pParams->pPrinterName ) ) ); DBGMSG( DBG_TRACE, ("pPortName "TSTR"\n", DBGSTR( pParams->pPortName ) ) ); DBGMSG( DBG_TRACE, ("pModelName "TSTR"\n", DBGSTR( pParams->pModelName ) ) ); DBGMSG( DBG_TRACE, ("pInfFileName "TSTR"\n", DBGSTR( pParams->pInfFileName ) ) ); DBGMSG( DBG_TRACE, ("pBasePrinterName "TSTR"\n", DBGSTR( pParams->pBasePrinterName) ) ); DBGMSG( DBG_TRACE, ("pMachineName "TSTR"\n", DBGSTR( pParams->pMachineName ) ) ); DBGMSG( DBG_TRACE, ("pSourcePath "TSTR"\n", DBGSTR( pParams->pSourcePath ) ) ); DBGMSG( DBG_TRACE, ("pszCmdLine "TSTR"\n", DBGSTR( pParams->pszCmdLine ) ) ); DBGMSG( DBG_TRACE, ("pBinFileName "TSTR"\n", DBGSTR( pParams->pBinFileName ) ) );
BOOL bRetval = FALSE;
switch( iFunction ) { case kInstallLocalPrinter: case kDeleteLocalPrinter: case kInstallPrinterDriver: case kEnumPerMachineConnections: case kServerProperties: case kCommandHelp: bRetval = TRUE; break;
case kInstallLocalPrinterWithInf: if( pParams->pInfFileName ) { bRetval = TRUE; } break;
case kSetAsDefault: case kAddPerMachineConnection: case kDeletePerMachineConnection: case kInstallNetPrinter: case kDeleteNetPrinter: case kWin32QueueView: case kProperties: case kDocumentDefaults: case kPrintTestPage: case kPrinterGetSettings: case kPrinterSetSettings: if( pParams->pPrinterName ) { bRetval = TRUE; } else { pParams->dwLastError = ERROR_INVALID_PRINTER_NAME; } break;
case kInstallPrinterWithInf: if( pParams->pModelName && pParams->pInfFileName && pParams->pPortName ) { bRetval = TRUE;
if( pParams->Flags.IsWebPointAndPrint ) { //
// Commenting out pBinFileName - for local cab install for wp&p the bin file
// won't exist. This may be fixed if syncing to the server is added and
// this could be put back then. - pvine
//
bRetval = pParams->pPrinterName /*&& pParams->pBinFileName */? TRUE : FALSE; } else if( pParams->Flags.IsDontAutoGenerateName ) { bRetval = pParams->pBasePrinterName != NULL; } } break;
case kPrinterPersist: case kPrinterRestore: bRetval = pParams->pPrinterName && pParams->pBinFileName ? TRUE : FALSE; break;
case kDeletePrinterDriver: case kInstallDriverWithInf: if( pParams->pModelName ) { bRetval = TRUE; } break;
case kUnknown: pParams->dwLastError = ERROR_INVALID_FUNCTION; bRetval = FALSE; break; }
if( !bRetval && ERROR_SUCCESS == pParams->dwLastError ) { //
// An invalid parameter has been passed.
//
pParams->dwLastError = ERROR_INVALID_PARAMETER; }
return bRetval; }
/*++
Routine Name:
bExecuteCommand
Routine Description:
Executes the command from the rundll32 command line after it has parsed.
Arguments:
hwnd - parent window handle. iFunction - Function code. pParams - pointer to paramter structure.
Return Value:
TRUE function complete ok. FALSE error occurred.
--*/ BOOL bExecuteCommand( IN HWND hwnd, IN INT iFunction, IN AParams *pParams ) { BOOL bRetval = TRUE; TCHAR szBuffer[kPrinterBufMax]; UINT uSize = COUNTOF( szBuffer );
DBGMSG( DBG_TRACE, ("Function %d\n", iFunction ) );
szBuffer[0] = TEXT('\0');
if( pParams->pPrinterName ) { _tcsncpy( szBuffer, pParams->pPrinterName, COUNTOF( szBuffer ) ); }
//
// Dispatch the specified function.
//
// !!Policy!! if a command is executed then it is responsible
// for displaying any error UI i.e message boxes.
//
switch( iFunction ) { case kInstallNetPrinter: (VOID)bPrinterSetup( NULL, MSP_NETPRINTER, MAX_PATH, szBuffer, &uSize, pParams->pMachineName ); break;
case kDeleteNetPrinter: bRetval = bPrinterNetRemove( NULL, szBuffer, pParams->Flags.IsQuiet ); break;
case kDeleteLocalPrinter: bRetval = bRemovePrinter( NULL, szBuffer, pParams->pMachineName, pParams->Flags.IsQuiet ); break;
case kInstallPrinterDriver: bRetval = bDriverSetupNew( NULL, TWizard::kDriverInstall, MAX_PATH, szBuffer, &uSize, pParams->pMachineName, 0, pParams->Flags.IsWizardRestartable ); break;
case kInstallLocalPrinter: bRetval = bPrinterSetupNew( NULL, TWizard::kPrinterInstall, MAX_PATH, szBuffer, &uSize, pParams->pMachineName, NULL, pParams->Flags.IsWizardRestartable ); break;
case kInstallLocalPrinterWithInf: bRetval = bPrinterSetupNew( NULL, TWizard::kPrinterInstall, MAX_PATH, szBuffer, &uSize, pParams->pMachineName, pParams->pInfFileName, FALSE ); break;
case kInstallDriverWithInf: bRetval = bDoInfDriverInstall( pParams ); break;
case kInstallPrinterWithInf: bRetval = bDoInfPrinterInstall( pParams ); break;
case kAddPerMachineConnection: vAddPerMachineConnection(pParams->pMachineName,pParams->pPrinterName,pParams->pProvider,pParams->Flags.IsQuiet); break;
case kDeletePerMachineConnection: vDeletePerMachineConnection(pParams->pMachineName,pParams->pPrinterName,pParams->Flags.IsQuiet); break;
case kEnumPerMachineConnections: vEnumPerMachineConnections(pParams->pMachineName,pParams->pInfFileName,pParams->Flags.IsQuiet); break;
case kWin32QueueView: vQueueCreate( NULL, pParams->pPrinterName, SW_SHOW, TRUE ); break;
case kProperties: vPrinterPropPages( NULL, pParams->pPrinterName, SW_SHOW, MAKELPARAM( pParams->dwSheet+256, 0 )); break;
case kDocumentDefaults: vDocumentDefaults( NULL, pParams->pPrinterName, SW_SHOW, MAKELPARAM( pParams->dwSheet, 1 )); break;
case kServerProperties: vServerPropPages( NULL, pParams->pPrinterName, SW_SHOW, MAKELPARAM( pParams->dwSheet, 1 )); break;
case kDeletePrinterDriver: bRetval = bDoDriverRemoval( pParams ); break;
case kSetAsDefault: bRetval = SetDefaultPrinter( pParams->pPrinterName ); break;
case kPrintTestPage: bRetval = bDoPrintTestPage( hwnd, pParams->pPrinterName ); break;
case kPrinterGetSettings: bRetval = bDoGetPrintSettings( pParams ); break;
case kPrinterSetSettings: bRetval = bDoSetPrintSettings( pParams ); break;
case kPrinterPersist: bRetval = bDoPersistPrinterSettings( kPrinterPersist , pParams ); break;
case kPrinterRestore: bRetval = bDoPersistPrinterSettings( kPrinterRestore , pParams ); break;
case kCommandHelp: vUsage( pParams ); break;
case kUnknown: default: bRetval = TRUE; break; }
//
// Some of the functions do not setup pParams->dwLastError,
// so we must rely on the GetLastError() in this case.
//
if( !bRetval && ERROR_SUCCESS == pParams->dwLastError ) { pParams->dwLastError = GetLastError(); }
return bRetval; }
/*++
Routine Name:
vUsage
Routine Description:
Display a usage message for the rundll switches.
Arguments:
Nothing.
Return Value:
None.
--*/ VOID vUsage( IN AParams *pParams ) { TStatusB bStatus; TString strTemp;
if (!pParams->Flags.IsQuiet) { TRunDllDisplay Usage( NULL );
if (VALID_OBJ( Usage )) { #ifdef COMMAND_SPECIFIC_HELP
if( pParams->ac ) { for( UINT i = 0; i < pParams->ac; i++ ) { bStatus DBGCHK = Usage.WriteOut( pParams->av[i] ); bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n") ); } } else #endif
{ //
// Note we do not check the return values of the string operations
// because bombing out is just as bad as printing an empty string. The
// string class will prevent us from ever crashing.
//
bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_RUNDLL_TITLE ); bStatus DBGCHK = Usage.SetTitle( strTemp ); bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_RUNDLL_USAGE ); bStatus DBGCHK = Usage.WriteOut( strTemp );
for( UINT i = IDS_RUNDLL_OPTION0; i <= IDS_RUNDLL_OPTION_END; i++ ) { bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n ") ); bStatus DBGCHK = strTemp.bLoadString( ghInst, i ); bStatus DBGCHK = Usage.WriteOut( strTemp ); }
bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n\r\n") ); bStatus DBGCHK = strTemp.bLoadString( ghInst,IDS_RUNDLL_EXAMPLE0 ); bStatus DBGCHK = Usage.WriteOut( strTemp );
for( i = IDS_RUNDLL_EXAMPLE1; i <= IDS_RUNDLL_EXAMPLE_END; i++ ) { bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n ") ); bStatus DBGCHK = strTemp.bLoadString( ghInst, i ); bStatus DBGCHK = Usage.WriteOut( strTemp ); } } Usage.bDoModal(); } } }
/*++
Routine Name:
bDoPersistPrinterSettings
Routine Description:
Store printer settings into file Calls Re/StorePrinterSettings with args : pParams->pPrinterName, pParams->pBinFileName and flags builded upon pParams->av if pParams->ac == 0 , all setttings will be stored/restored
For restoring settings PRINTER_ALL_ACCESS required for specified printer
Arguments:
iFunction specify what function should be called ( Store/RestorePrinterSettings ) AParams* ptr to AParam structure
Return Value:
TRUE if Re/StorePrinterSettings SUCCEEDED. FALSE otherwise
--*/ BOOL bDoPersistPrinterSettings( IN INT iFunction, IN AParams *pParams ) { DWORD dwFlags = 0; UINT idx; UINT ParamIdx; UINT OptionIdx; HRESULT hr;
struct ParamEntry { TCHAR Option; DWORD Flag;
};
static ParamEntry PrintSettings_ParamTable [] = { {TEXT('2'), PRST_PRINTER_INFO_2}, {TEXT('7'), PRST_PRINTER_INFO_7}, {TEXT('c'), PRST_COLOR_PROF}, {TEXT('d'), PRST_PRINTER_DATA}, {TEXT('s'), PRST_PRINTER_SEC}, {TEXT('g'), PRST_PRINTER_DEVMODE}, {TEXT('u'), PRST_USER_DEVMODE}, {TEXT('r'), PRST_RESOLVE_NAME}, {TEXT('f'), PRST_FORCE_NAME}, {TEXT('p'), PRST_RESOLVE_PORT}, {TEXT('h'), PRST_RESOLVE_SHARE}, {TEXT('H'), PRST_DONT_GENERATE_SHARE}, {TEXT('m'), PRST_MINIMUM_SETTINGS}, {0, 0}, };
// for every entry in table
for (ParamIdx = 0 ; ParamIdx < pParams->ac; ParamIdx++ ) { //for every option argv
for (idx = 0; PrintSettings_ParamTable[idx].Option; idx++) { OptionIdx = 0;
//for every char in option argv
while(pParams->av[ParamIdx][OptionIdx]) { if(OptionIdx > 0) { hr = E_FAIL; goto End; }
if(PrintSettings_ParamTable[idx].Option == pParams->av[ParamIdx][OptionIdx]) { // apply flags if in table
dwFlags |= PrintSettings_ParamTable[idx].Flag;
DBGMSG(DBG_TRACE , ("Char %c\n" , pParams->av[ParamIdx][OptionIdx]));
}
OptionIdx++; }
} }
if((dwFlags & PRST_FORCE_NAME) && (dwFlags & PRST_RESOLVE_NAME)) { hr = E_FAIL; goto End; }
//
// if no "printer" flags specified , set flags to PRST_ALL_SETTINGS
//
if(!(dwFlags & PRST_ALL_SETTINGS)) { dwFlags |= PRST_ALL_SETTINGS; }
hr = (iFunction == kPrinterRestore) ? RestorePrinterSettings( pParams->pPrinterName, pParams->pBinFileName, dwFlags) : StorePrinterSettings( pParams->pPrinterName, pParams->pBinFileName, dwFlags) ;
End:
return SUCCEEDED(hr);
}
/*++
Routine Name:
bDoWebPnpPreInstall
Routine Description:
Do Web Point and Print Pre installation tasks.
Arguments:
pParams - pointer to paramter structure. pfConnection - pointer where to return connection status
Return Value:
TRUE Web Point and Print code was successfull, FALSE error occurred.
--*/ BOOL bDoWebPnpPreInstall( IN AParams *pParams ) { TStatusB bStatus;
//
// Inform the point and print code pre entry.
//
bStatus DBGCHK = SUCCEEDED(Winspool_WebPnpEntry( pParams->pszCmdLine ));
//
// If something failed return the last error.
//
if( !bStatus ) { pParams->dwLastError = GetLastError(); }
return bStatus; }
/*++
Routine Name:
bDoInfPrinterInstall
Routine Description:
Do inf based printer installation.
Arguments:
pParams - pointer to paramter structure.
Return Value:
None.
--*/ BOOL bDoInfPrinterInstall( IN AParams *pParams ) { TStatusB bStatus; TCHAR szBuffer[kPrinterBufMax];
//
// Assume success.
//
bStatus DBGNOCHK = TRUE;
//
// If we are invoked for a Web Point and Pint install.
//
if( bStatus && pParams->Flags.IsWebPointAndPrint ) { //
// Inform the point and print code pre entry.
//
bStatus DBGCHK = bDoWebPnpPreInstall( pParams ); }
//
// If web pnp pre installed succeeded.
//
if( bStatus ) { TInfInstall II; TParameterBlock PB;
ZeroMemory( &II, sizeof( II ) ); ZeroMemory( &PB, sizeof( PB ) ); ZeroMemory( szBuffer, sizeof( szBuffer ) );
if( pParams->pBasePrinterName ) { _tcsncpy( szBuffer, pParams->pBasePrinterName, COUNTOF( szBuffer ) ); }
II.cbSize = sizeof( II ); II.pszServerName = pParams->pMachineName; II.pszInfName = pParams->pInfFileName; II.pszModelName = pParams->pModelName; II.pszPortName = pParams->pPortName; II.pszSourcePath = pParams->pSourcePath; II.pszPrinterNameBuffer = szBuffer; II.cchPrinterName = COUNTOF( szBuffer );
//
// If this is a web point and print install then set the flags
// to indicate that we want to create the masq printer.
//
II.dwFlags = 0; II.dwFlags |= pParams->Flags.IsWebPointAndPrint ? kPnPInterface_WebPointAndPrint : 0; II.dwFlags |= pParams->Flags.IsQuiet ? kPnPInterface_Quiet : 0; II.dwFlags |= pParams->Flags.IsNoSharing ? kPnPInterface_NoShare : 0; II.dwFlags |= pParams->Flags.IsUseExistingDriver ? kPnpInterface_UseExisting : 0; II.dwFlags |= pParams->Flags.IsUnknownDriverPrompt ? kPnpInterface_PromptIfUnknownDriver : 0; II.dwFlags |= pParams->Flags.IsHydraSpecific ? kPnpInterface_HydraSpecific : 0; II.dwFlags |= pParams->Flags.IsPromptForNeededFiles ? kPnPInterface_PromptIfFileNeeded : 0; II.dwFlags |= pParams->Flags.IsShared ? kPnPInterface_Share : 0; II.dwFlags |= pParams->Flags.IsDontAutoGenerateName ? kPnPInterface_DontAutoGenerateName : 0; II.dwFlags |= pParams->Flags.IsSupressSetupUI ? kPnPInterface_SupressSetupUI : 0;
PB.pInfInstall = &II;
pParams->dwLastError = PnPInterface( kInfInstall, &PB );
bStatus DBGNOCHK = (pParams->dwLastError == ERROR_SUCCESS); }
//
// If we succeeded and this is a web point and print event.
//
if( bStatus && pParams->Flags.IsWebPointAndPrint ) { //
// Inform the web point and print code that the printer was
// installed, they can do ay post processing here.
//
bStatus DBGCHK = SUCCEEDED(Winspool_WebPnpPostEntry( FALSE, pParams->pBinFileName, pParams->pPortName, szBuffer )); }
return pParams->dwLastError == ERROR_SUCCESS ? TRUE : FALSE; }
/*++
Routine Name:
bDoInfDriverInstall
Routine Description:
Do inf based printer driver installation.
Arguments:
pParams - pointer to paramter structure.
Return Value:
None.
--*/ BOOL bDoInfDriverInstall( IN AParams *pParams ) { TInfDriverInstall II = {0}; TParameterBlock PB = {0};
II.cbSize = sizeof( II ); II.pszServerName = pParams->pMachineName; II.pszInfName = pParams->pInfFileName; II.pszModelName = pParams->pModelName; II.pszSourcePath = pParams->pSourcePath; II.pszVersion = pParams->pVersion; II.pszArchitecture = pParams->pArchitecture;
II.dwFlags = 0; II.dwFlags |= pParams->Flags.IsQuiet ? kPnPInterface_Quiet : 0; II.dwFlags |= pParams->Flags.IsWindowsUpdate ? kPnPInterface_WindowsUpdate : 0; II.dwFlags |= pParams->Flags.IsUseNonLocalizedStrings ? kPnPInterface_UseNonLocalizedStrings : 0; II.dwFlags |= pParams->Flags.IsSupressSetupUI ? kPnPInterface_SupressSetupUI : 0;
PB.pInfDriverInstall = &II;
pParams->dwLastError = PnPInterface( kInfDriverInstall, &PB );
return pParams->dwLastError == ERROR_SUCCESS; }
/*++
Routine Name:
bDoDriverRemoval
Routine Description:
Do driver delete
Arguments:
pParams - pointer to paramter structure.
Return Value:
None.
--*/ BOOL bDoDriverRemoval( IN AParams *pParams ) { TDriverRemoval II = {0}; TParameterBlock PB = {0};
II.cbSize = sizeof( II ); II.pszServerName = pParams->pMachineName; II.pszModelName = pParams->pModelName; II.pszVersion = pParams->pVersion; II.pszArchitecture = pParams->pArchitecture;
II.dwFlags = 0; II.dwFlags |= pParams->Flags.IsUseNonLocalizedStrings ? kPnPInterface_UseNonLocalizedStrings : 0; II.dwFlags |= pParams->Flags.IsQuiet ? kPnPInterface_Quiet : 0; II.dwFlags |= pParams->Flags.IsSupressSetupUI ? kPnPInterface_SupressSetupUI : 0;
PB.pDriverRemoval = &II;
pParams->dwLastError = PnPInterface( kDriverRemoval, &PB );
if( ERROR_UNKNOWN_PRINTER_DRIVER == pParams->dwLastError ) { // this error code is used primarily for blocking bad
// oem drivers so the default message used is pretty
// incorrect. remap the message to better one based on
// the context
CMsgBoxCounter::SetMsg(IDS_ERROR_DRIVER_DOESNT_EXISTS); }
return pParams->dwLastError == ERROR_SUCCESS; }
/********************************************************************
Setting and Getting printer information methods.
********************************************************************/
static TSelect::SelectionVal PrintSettings_ValueTable [] = { {IDS_RUNDLL_SET_PAUSE, PRINTER_CONTROL_PAUSE, OFFSETOF( PRINTER_INFO_2, Status )}, {IDS_RUNDLL_SET_RESUME, PRINTER_CONTROL_RESUME, OFFSETOF( PRINTER_INFO_2, Status )}, {IDS_RUNDLL_SET_PURGE, PRINTER_CONTROL_PURGE, OFFSETOF( PRINTER_INFO_2, Status )}, {NULL, 0, NULL}};
static TSelect::SelectionBit PrintSettings_BitTable [] = { {IDS_RUNDLL_SET_QUEUED, PRINTER_ATTRIBUTE_QUEUED, TSelect::kNop}, {IDS_RUNDLL_SET_DIRECT, PRINTER_ATTRIBUTE_DIRECT, TSelect::kNop}, {IDS_RUNDLL_SET_DEFAULT, PRINTER_ATTRIBUTE_DEFAULT, TSelect::kNop}, {IDS_RUNDLL_SET_SHARED, PRINTER_ATTRIBUTE_SHARED, TSelect::kNop}, {IDS_RUNDLL_SET_HIDDEN, PRINTER_ATTRIBUTE_HIDDEN, TSelect::kNop}, {IDS_RUNDLL_SET_NETWORK, PRINTER_ATTRIBUTE_NETWORK, TSelect::kNop}, {IDS_RUNDLL_SET_LOCAL, PRINTER_ATTRIBUTE_LOCAL, TSelect::kNop}, {IDS_RUNDLL_SET_ENABLEDEVQ, PRINTER_ATTRIBUTE_ENABLE_DEVQ, TSelect::kNop}, {IDS_RUNDLL_SET_KEEPPRINTEDJOBS,PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS, TSelect::kNop}, {IDS_RUNDLL_SET_DOCOMPLETEFIRST,PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,TSelect::kNop}, {IDS_RUNDLL_SET_WORKOFFLINE, PRINTER_ATTRIBUTE_WORK_OFFLINE, TSelect::kNop}, {IDS_RUNDLL_SET_ENABLEBIDI, PRINTER_ATTRIBUTE_ENABLE_BIDI, TSelect::kNop}, {IDS_RUNDLL_SET_RAWONLY, PRINTER_ATTRIBUTE_RAW_ONLY, TSelect::kNop}, {IDS_RUNDLL_SET_PUBLISHED, PRINTER_ATTRIBUTE_PUBLISHED, TSelect::kNop}, {0, 0, TSelect::kNop}};
static TSelect::Selection PrintSettings_Table [] = { {IDS_RUNDLL_SET_PRINTERNAME, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pPrinterName ) }, {IDS_RUNDLL_SET_SHARENAME, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pShareName ) }, {IDS_RUNDLL_SET_PORTNAME, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pPortName ) }, {IDS_RUNDLL_SET_DRIVERNAME, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pDriverName ) }, {IDS_RUNDLL_SET_COMMENT, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pComment ) }, {IDS_RUNDLL_SET_LOCATION, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pLocation ) }, {IDS_RUNDLL_SET_SEPFILE, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pSepFile ) }, {IDS_RUNDLL_SET_PRINTPROCESSOR, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pPrintProcessor )}, {IDS_RUNDLL_SET_DATATYPE, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pDatatype ) }, {IDS_RUNDLL_SET_PARAMETERS, TSelect::kString, NULL, OFFSETOF( PRINTER_INFO_2, pParameters ) }, {IDS_RUNDLL_SET_ATTRIBUTES, TSelect::kBitTable, PrintSettings_BitTable, OFFSETOF( PRINTER_INFO_2, Attributes ) }, {IDS_RUNDLL_SET_PRIORITY, TSelect::kInt, NULL, OFFSETOF( PRINTER_INFO_2, Priority ) }, {IDS_RUNDLL_SET_DEFAULTPRIORITY,TSelect::kInt, NULL, OFFSETOF( PRINTER_INFO_2, DefaultPriority ) }, {IDS_RUNDLL_SET_STARTTIME, TSelect::kInt, NULL, OFFSETOF( PRINTER_INFO_2, StartTime ) }, {IDS_RUNDLL_SET_UNTILTIME, TSelect::kInt, NULL, OFFSETOF( PRINTER_INFO_2, UntilTime ) }, {IDS_RUNDLL_SET_STATUS, TSelect::kValTable, PrintSettings_ValueTable,OFFSETOF( PRINTER_INFO_2, Status ) }, {NULL, TSelect::kNone, NULL, NULL }};
/*++
Routine Name:
bDoGetPrintSettings
Routine Description:
Get the specified printer settings.
Arguments:
pParams - pointer to paramter structure.
Return Value:
TRUE success, FALSE error.
--*/
BOOL bDoGetPrintSettings( IN AParams *pParams ) { DBGMSG( DBG_TRACE, ( "bDoGetPrintSettings\n" ) ); return PrintSettings_DisplayInformation( pParams, PrintSettings_Table ); }
/*++
Routine Name:
bDoSetPrintSettings
Routine Description:
Set the specified printer settings.
Arguments:
pParams - pointer to paramter structure.
Return Value:
TRUE success, FALSE error.
--*/ BOOL bDoSetPrintSettings( IN AParams *pParams ) { DBGMSG( DBG_TRACE, ( "bDoSetPrintSettings\n" ) ); DBGMSG( DBG_TRACE, ( "Argument count %d.\n", pParams->ac ) );
TStatusB bStatus; bStatus DBGNOCHK = FALSE; TSelect Select; PRINTER_INFO_2 Info = {0};
Info.Attributes = (DWORD)-1; Info.Priority = (DWORD)-1; Info.DefaultPriority = (DWORD)-1; Info.StartTime = (DWORD)-1; Info.UntilTime = (DWORD)-1; Info.Status = (DWORD)-1;
//
// Validate command arguments
//
if( !PrintSettings_ValidateArguments( pParams ) ) { DBGMSG( DBG_WARN, ( "Argument validation failed.\n" ) ); return pParams->dwLastError == ERROR_SUCCESS; }
//
// Lookup the printer setting command.
//
for( UINT i = 0; i < pParams->ac; i += 2 ) { if( (i+0 < pParams->ac) && (i+1 < pParams->ac) ) { bStatus DBGCHK = Select.bLookup( PrintSettings_Table, &Info, pParams->av[i], pParams->av[i+1] );
if( !bStatus ) { DBGMSG( DBG_WARN, ( "Invalid key name found.\n" ) ); pParams->dwLastError = ERROR_INVALID_PARAMETER; break; } } else { DBGMSG( DBG_WARN, ( "Unmatched key / value pair arguments\n" ) ); pParams->dwLastError = ERROR_INVALID_PARAMETER; bStatus DBGNOCHK = FALSE; break; } }
//
// Set the printer data.
//
if( bStatus ) { //
// Set the printer information.
//
bStatus DBGCHK = PrintSettings_SetInfo( pParams, Info );
if( !bStatus ) { DBGMSG( DBG_TRACE, ( "PrintSettings_SetInfo failed with %d\n", pParams->dwLastError ) ); } }
return bStatus; }
/*++
Routine Name:
PrintSettings_ValidateArguments
Routine Description:
Validate the command line arguments
Arguments:
pParams - pointer to paramter structure.
Return Value:
TRUE success, FALSE error.
--*/ BOOL PrintSettings_ValidateArguments( IN AParams *pParams ) { TStatusB bStatus; bStatus DBGNOCHK = FALSE; TString strHelp1; TString strHelp2;
//
// There must be at least one additional argumet.
//
if( !(pParams->ac >= 1) ) { DBGMSG( DBG_WARN, ( "Insufficent number of additional arguments.\n" ) ); pParams->dwLastError = ERROR_INVALID_PARAMETER; return bStatus; }
//
// If a help command was specified.
//
bStatus DBGCHK = strHelp1.bLoadString( ghInst, IDS_RUNDLL_HELP1 ); bStatus DBGCHK = strHelp2.bLoadString( ghInst, IDS_RUNDLL_HELP2 ); if( !_tcsicmp( pParams->av[0], strHelp1 ) || !_tcsicmp( pParams->av[0], strHelp2 ) ) { pParams->dwLastError = ERROR_SUCCESS; PrintSettings_DisplayHelp( pParams, PrintSettings_Table ); return FALSE; }
//
// Success we have validated the arguments.
//
bStatus DBGNOCHK = TRUE;
return bStatus; }
/*++
Routine Name:
PrintSettings_SetInfo
Routine Description:
Set the printer info data.
Arguments:
Info - Reference to printer info data. pParams - pointer to paramter structure.
Return Value:
TRUE success, FALSE error.
--*/
BOOL PrintSettings_SetInfo( IN AParams *pParams, IN PRINTER_INFO_2 &Info ) { DBGMSG( DBG_TRACE, ( "PrintSettings_SetInfo\n" ) );
TStatus Status; TStatusB bStatus;
bStatus DBGNOCHK = FALSE;
HANDLE hPrinter = NULL; PPRINTER_INFO_2 pInfo = NULL; DWORD cbInfo = 0; DWORD dwAccess = 0; DWORD dwOldAttributes = 0; DWORD dwNewAttributes = 0;
//
// Open the printer.
//
Status DBGCHK = TPrinter::sOpenPrinter( pParams->pPrinterName, &dwAccess, &hPrinter );
if( Status == ERROR_SUCCESS ) { //
// Get the printer data.
//
bStatus DBGNOCHK = VDataRefresh::bGetPrinter( hPrinter, 2, (PVOID *)&pInfo, (PDWORD)&cbInfo );
//
// Merge in any changed fields.
//
if( bStatus ) { TSelect Select;
//
// Convert the bit table to a value.
//
Select.bApplyBitTableToValue( PrintSettings_BitTable, pInfo->Attributes, &Info.Attributes );
//
// Publishing and UnPublishing needs to be special cased, since this setting is
// not done in the printer info 2 structure. The published bit is a read only
// attribute in the printer info 2, the publish state is changed using set printer
// info 7.
//
dwOldAttributes = pInfo->Attributes; dwNewAttributes = Info.Attributes != -1 ? Info.Attributes : pInfo->Attributes;
//
// Copy the changed date into the info sturcture.
//
pInfo->pPrinterName = Info.pPrinterName ? Info.pPrinterName : pInfo->pPrinterName; pInfo->pShareName = Info.pShareName ? Info.pShareName : pInfo->pShareName; pInfo->pPortName = Info.pPortName ? Info.pPortName : pInfo->pPortName; pInfo->pDriverName = Info.pDriverName ? Info.pDriverName : pInfo->pDriverName; pInfo->pComment = Info.pComment ? Info.pComment : pInfo->pComment; pInfo->pLocation = Info.pLocation ? Info.pLocation : pInfo->pLocation; pInfo->pSepFile = Info.pSepFile ? Info.pSepFile : pInfo->pSepFile; pInfo->pDatatype = Info.pDatatype ? Info.pDatatype : pInfo->pDatatype; pInfo->pParameters = Info.pParameters ? Info.pParameters : pInfo->pParameters;
pInfo->Attributes = Info.Attributes != -1 ? Info.Attributes : pInfo->Attributes; pInfo->Priority = Info.Priority != -1 ? Info.Priority : pInfo->Priority; pInfo->DefaultPriority = Info.DefaultPriority != -1 ? Info.DefaultPriority : pInfo->DefaultPriority; pInfo->StartTime = Info.StartTime != -1 ? Info.StartTime : pInfo->StartTime; pInfo->UntilTime = Info.UntilTime != -1 ? Info.UntilTime : pInfo->UntilTime; }
//
// Set the changed printer data.
//
if( bStatus ) { bStatus DBGCHK = SetPrinter( hPrinter, 2, (PBYTE)pInfo, 0 );
if( bStatus ) { if( Info.Status != -1 ) { bStatus DBGCHK = SetPrinter( hPrinter, 0, NULL, Info.Status ); } } }
//
// Handle the printer publishing case.
//
if( bStatus ) { //
// Only do something if the attributes are different.
//
if( dwOldAttributes != dwNewAttributes ) { //
// If the current printer state is not shared and it
// was previously published then unpublish it now.
//
if(!(pInfo->Attributes & PRINTER_ATTRIBUTE_SHARED) && dwOldAttributes & PRINTER_ATTRIBUTE_PUBLISHED) { dwNewAttributes &= ~PRINTER_ATTRIBUTE_PUBLISHED; }
//
// Only unpublish requests or shared printer publish requests.
//
bStatus DBGCHK = !(dwNewAttributes & PRINTER_ATTRIBUTE_PUBLISHED) || (dwNewAttributes & PRINTER_ATTRIBUTE_PUBLISHED && pInfo->Attributes & PRINTER_ATTRIBUTE_SHARED);
if(bStatus) { PRINTER_INFO_7 Info7 = {0};
Info7.dwAction = (dwNewAttributes & PRINTER_ATTRIBUTE_PUBLISHED) ? DSPRINT_PUBLISH : DSPRINT_UNPUBLISH;
bStatus DBGCHK = SetPrinter( hPrinter, 7, (PBYTE)&Info7, 0 );
//
// Printer info 7 fails with ERROR_IO_PENDING when the publishing is occurring
// in the background. For the rundll32 interface just return success.
//
if(!bStatus && (GetLastError() == ERROR_IO_PENDING)) { SetLastError(ERROR_SUCCESS); bStatus DBGNOCHK = TRUE; } } else { SetLastError(ERROR_INVALID_PARAMETER); } } }
//
// Release the printer info data.
//
FreeMem( pInfo );
//
// Close the printer handle if one was opened.
//
if( hPrinter ) { ClosePrinter( hPrinter ); } }
//
// If something failed preserve the last error.
//
if( !bStatus ) { pParams->dwLastError = GetLastError(); }
return bStatus; }
/*++
Routine Name:
PrintSettings_DisplayHelp
Routine Description:
Displays the printer settings command arguments.
Arguments:
pParams - pointer to paramter structure. pSelection - pointer argument selection table.
Return Value:
TRUE success, FALSE error.
--*/ BOOL PrintSettings_DisplayHelp( IN AParams *pParams, IN TSelect::Selection *pSelection ) { DBGMSG( DBG_TRACE, ( "PrintSettings_DisplayHelp\n" ) );
TStatusB bStatus; TRunDllDisplay Usage( NULL, pParams->pInfFileName, (pParams->pInfFileName && *pParams->pInfFileName) ? TRunDllDisplay::kFile : TRunDllDisplay::kEditBox );
bStatus DBGNOCHK = VALID_OBJ( Usage );
if( bStatus ) { TString strTemp; TString strString; TString strInt; TString strStart; TString strEnd; TString strSep; TString strFormat; TString strBit; LPCTSTR pszType;
//
// Set the title.
//
bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_RUNDLL_SET_ATTRIBUTE_TITLE ); bStatus DBGCHK = Usage.SetTitle( strTemp );
//
// Set the usage example.
//
bStatus DBGCHK = strTemp.bLoadString( ghInst, IDS_RUNDLL_SET_ATTRIBUTE_USAGE ); bStatus DBGCHK = Usage.WriteOut( strTemp ); bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n") );
//
// Load some constant strings.
//
bStatus DBGCHK = strString.bLoadString( ghInst, IDS_RUNDLL_STRING ); bStatus DBGCHK = strInt.bLoadString( ghInst, IDS_RUNDLL_INTEGER ); bStatus DBGCHK = strStart.bLoadString( ghInst, IDS_RUNDLL_START ); bStatus DBGCHK = strEnd.bLoadString( ghInst, IDS_RUNDLL_END ); bStatus DBGCHK = strSep.bLoadString( ghInst, IDS_RUNDLL_SEP ); bStatus DBGCHK = strFormat.bLoadString( ghInst, IDS_RUNDLL_FORMAT );
for( ; pSelection->iKeyWord; pSelection++ ) { switch( pSelection->eDataType ) { case TSelect::kInt: pszType = strInt; break;
case TSelect::kString: pszType = strString; break;
case TSelect::kValTable: case TSelect::kBitTable: { bStatus DBGCHK = strBit.bUpdate( strStart ); TSelect::SelectionBit *pSel = (TSelect::SelectionBit *)pSelection->pTable; for( ; pSel->iKeyWord; pSel++ ) { bStatus DBGCHK = strTemp.bLoadString( ghInst, pSel->iKeyWord ); bStatus DBGCHK = strBit.bCat( strTemp ); if( (pSel+1)->iKeyWord ) { bStatus DBGCHK = strBit.bCat( strSep ); } } bStatus DBGCHK = strBit.bCat( strEnd ); pszType = strBit; } break;
default: pszType = gszNULL; break; }
bStatus DBGCHK = strTemp.bLoadString( ghInst, pSelection->iKeyWord ); bStatus DBGCHK = strTemp.bFormat( strFormat, (LPCTSTR)strTemp, pszType ); bStatus DBGCHK = Usage.WriteOut( strTemp ); bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n") ); }
bStatus DBGCHK = strTemp.bLoadString( ghInst,IDS_RUNDLL_EXAMPLE0 ); bStatus DBGCHK = Usage.WriteOut( strTemp );
for( UINT i = IDS_RUNDLL_SET_EXAMPLE1; i <= IDS_RUNDLL_SET_EXAMPLE_END; i++ ) { bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n ") ); bStatus DBGCHK = strTemp.bLoadString( ghInst, i ); bStatus DBGCHK = Usage.WriteOut( strTemp ); }
bStatus DBGCHK = Usage.bDoModal(); }
return bStatus; }
/*++
Routine Name:
PrintSettings_DisplayInformation
Routine Description:
Displays the printer settings
Arguments:
pParams - pointer to paramter structure. pSelection - pointer argument selection table.
Return Value:
TRUE success, FALSE error.
--*/ BOOL PrintSettings_DisplayInformation( IN AParams *pParams, IN TSelect::Selection *pSelection ) { DBGMSG( DBG_TRACE, ( "PrintSettings_DisplayInformation\n" ) );
TStatus Status( DBG_WARN ); TString strTemp; TString strKeyword; TString strFormat1; TString strFormat2; TString strTitle; TStatusB bStatus;
bStatus DBGNOCHK = FALSE; DWORD dwAccess = 0; HANDLE hPrinter = NULL; PPRINTER_INFO_2 pInfo = NULL; DWORD cbInfo = 0;
//
// Open the printer.
//
Status DBGCHK = TPrinter::sOpenPrinter( pParams->pPrinterName, &dwAccess, &hPrinter );
if( Status == ERROR_SUCCESS ) { //
// Get the printer data.
//
bStatus DBGNOCHK = VDataRefresh::bGetPrinter( hPrinter, 2, (PVOID *)&pInfo, (PDWORD)&cbInfo );
if( bStatus ) { //
// Display the printer data.
//
TRunDllDisplay Usage( NULL, pParams->pInfFileName, (pParams->pInfFileName && *pParams->pInfFileName) ? TRunDllDisplay::kFile : TRunDllDisplay::kEditBox );
bStatus DBGNOCHK = VALID_OBJ( Usage );
if( bStatus ) { Usage.vSetTabStops(64);
bStatus DBGCHK = strTitle.bLoadString( ghInst, IDS_RUNDLL_DISPLAY_TITLE ); bStatus DBGCHK = strTitle.bCat( pParams->pPrinterName ); Usage.SetTitle( strTitle );
bStatus DBGCHK = strFormat1.bLoadString( ghInst, IDS_RUNDLL_DISPLAY_FORMAT1 ); bStatus DBGCHK = strFormat2.bLoadString( ghInst, IDS_RUNDLL_DISPLAY_FORMAT2 );
for( ; pSelection->iKeyWord; pSelection++ ) { bStatus DBGCHK = strKeyword.bLoadString( ghInst, pSelection->iKeyWord );
switch( pSelection->eDataType ) { case TSelect::kString: bStatus DBGCHK = strTemp.bFormat( strFormat1, (LPCTSTR)strKeyword, *(LPCTSTR *)((PBYTE)pInfo+pSelection->iOffset) ); break;
case TSelect::kInt: bStatus DBGCHK = strTemp.bFormat( strFormat2, (LPCTSTR)strKeyword, *(UINT *)((PBYTE)pInfo+pSelection->iOffset) ); break;
case TSelect::kBitTable: bStatus DBGCHK = PrintSettings_DisplayAttributes( strTemp, pSelection, *(UINT *)((PBYTE)pInfo+pSelection->iOffset) ); bStatus DBGCHK = strTemp.bFormat( strFormat1, (LPCTSTR)strKeyword, (LPCTSTR)strTemp ); break;
case TSelect::kValTable: bStatus DBGCHK = PrintSettings_DisplayStatus( strTemp, pSelection, *(UINT *)((PBYTE)pInfo+pSelection->iOffset) ); bStatus DBGCHK = strTemp.bFormat( strFormat1, (LPCTSTR)strKeyword, (LPCTSTR)strTemp ); break;
default: bStatus DBGCHK = strTemp.bUpdate( NULL ); break; }
bStatus DBGCHK = Usage.WriteOut( strTemp ); bStatus DBGCHK = Usage.WriteOut( TEXT("\r\n") );
}
bStatus DBGCHK = Usage.bDoModal(); } }
//
// Release the printer info data.
//
FreeMem( pInfo );
//
// Close the printer handle if one was opened.
//
if( hPrinter ) { ClosePrinter( hPrinter ); } }
return bStatus; }
/*++
Routine Name:
PrintSettings_DisplayAttributes
Routine Description:
Get the current printer attributes in a displayable form.
Arguments:
Return Value:
TRUE success, FALSE error.
--*/ BOOL PrintSettings_DisplayAttributes( IN TString &strBit, IN TSelect::Selection *pSelection, IN UINT uAttributes ) { DBGMSG( DBG_TRACE, ( "PrintSettings_DisplayAttributes\n" ) );
TStatusB bStatus; TString strStart; TString strEnd; TString strSep; TString strTemp;
bStatus DBGCHK = strStart.bLoadString( ghInst, IDS_RUNDLL_START ); bStatus DBGCHK = strEnd.bLoadString( ghInst, IDS_RUNDLL_END ); bStatus DBGCHK = strSep.bLoadString( ghInst, IDS_RUNDLL_SEP );
TSelect::SelectionBit *pSel = (TSelect::SelectionBit *)pSelection->pTable;
bStatus DBGCHK = strBit.bUpdate( strStart );
for( ; pSel->iKeyWord; pSel++ ) { if( uAttributes & pSel->uBit ) { bStatus DBGCHK = strTemp.bLoadString( ghInst, pSel->iKeyWord ); bStatus DBGCHK = strBit.bCat( strTemp ); bStatus DBGCHK = strBit.bCat( strSep ); } }
bStatus DBGCHK = strBit.bCat( strEnd );
return TRUE; }
/*++
Routine Name:
PrintSettings_DisplayStatus
Routine Description:
Get the status in a displayable form.
Arguments:
Return Value:
TRUE success, FALSE error.
--*/ BOOL PrintSettings_DisplayStatus( IN TString &strVal, IN TSelect::Selection *pSelection, IN UINT uStatus ) { DBGMSG( DBG_TRACE, ( "PrintSettings_DisplayStatus\n" ) );
TStatusB bStatus; TString strStart; TString strEnd; TString strTemp;
bStatus DBGCHK = strStart.bLoadString( ghInst, IDS_RUNDLL_START ); bStatus DBGCHK = strEnd.bLoadString( ghInst, IDS_RUNDLL_END );
TSelect::SelectionVal *pSel = (TSelect::SelectionVal *)pSelection->pTable;
bStatus DBGCHK = strVal.bUpdate( strStart );
for( ; pSel->iKeyWord; pSel++ ) { if( uStatus == pSel->uValue ) { bStatus DBGCHK = strTemp.bLoadString( ghInst, pSel->iKeyWord ); bStatus DBGCHK = strVal.bCat( strTemp ); break; } }
bStatus DBGCHK = strVal.bCat( strEnd );
return TRUE; }
/********************************************************************
RunDll Usage
********************************************************************/
TRunDllDisplay:: TRunDllDisplay( IN HWND hWnd, IN LPCTSTR pszFileName, IN DisplayType Display ) : _hWnd( hWnd ), _bValid( FALSE ), _Display( Display ), _pFile( NULL ), _cxGrip( 0 ), _cyGrip( 0 ), _hwndGrip( NULL ), _cTabStop( 0 ), _dwTabStop( 0 ) { memset( &_ptLastSize, 0, sizeof(_ptLastSize) ); memset( &_ptMinTrack, 0, sizeof(_ptMinTrack) );
switch( _Display ) { case kFile: _pFile = new TFile( pszFileName ); _bValid = VALID_PTR( _pFile ); break;
case kEditBox: _bValid = TRUE; break;
default: SPLASSERT( FALSE ); _bValid = FALSE; break; } }
TRunDllDisplay:: ~TRunDllDisplay( VOID ) { if( _hwndGrip ) { DestroyWindow( _hwndGrip ); }
delete _pFile; }
BOOL TRunDllDisplay:: WriteOut( LPCTSTR pszData ) { SPLASSERT( pszData ); return _StringOutput.bCat(pszData); }
BOOL TRunDllDisplay:: bValid( VOID ) { return _bValid; }
VOID TRunDllDisplay:: vSetTabStops( IN UINT uTabStop ) { _cTabStop = 1; _dwTabStop = uTabStop; }
BOOL TRunDllDisplay:: bDoModal( VOID ) { TStatusB bStatus;
switch( _Display ) { case kEditBox: bStatus DBGCHK = (BOOL)DialogBoxParam( ghInst, MAKEINTRESOURCE( DLG_RUNDLL ), _hWnd, MGenericDialog::SetupDlgProc, (LPARAM)this ); break;
case kFile: bStatus DBGCHK = _pFile->bWrite( _StringOutput ); break;
default: bStatus DBGNOCHK = FALSE; break; }
return bStatus; }
BOOL TRunDllDisplay:: SetTitle( IN LPCTSTR pszData ) { TStatusB bStatus; bStatus DBGCHK = _StringTitle.bUpdate(pszData); return bStatus; }
BOOL TRunDllDisplay:: bSetUI( VOID ) { TStatusB bStatus;
bStatus DBGCHK = bSetEditText( _hDlg, IDC_RUNDLL_TITLE, _StringTitle ); bStatus DBGCHK = bSetEditText( _hDlg, IDC_RUNDLL_TEXT, _StringOutput ); SendDlgItemMessage( _hDlg, IDC_RUNDLL_TEXT, EM_SETMODIFY, TRUE, 0 );
//
// Set any applicable tab stops.
//
SendDlgItemMessage( _hDlg, IDC_RUNDLL_TEXT, EM_SETTABSTOPS, _cTabStop, (LPARAM)&_dwTabStop );
//
// Set the initial size.
//
RECT rect; GetWindowRect(_hDlg, &rect); _ptLastSize.x = rect.right - rect.left; _ptLastSize.y = rect.bottom - rect.top;
//
// Save the minimum track information.
//
_ptMinTrack.x = rect.right - rect.left; _ptMinTrack.y = rect.bottom - rect.top;
//
// Create the sizing grip.
//
RECT rc; GetClientRect(_hDlg, &rc);
_cxGrip = GetSystemMetrics(SM_CXVSCROLL); _cyGrip = GetSystemMetrics(SM_CYHSCROLL);
_hwndGrip = CreateWindow( TEXT("Scrollbar"), NULL, WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | SBS_BOTTOMALIGN | SBS_SIZEGRIP | SBS_SIZEBOXBOTTOMRIGHTALIGN, rc.right - _cxGrip, rc.bottom - _cyGrip, _cxGrip, _cyGrip, _hDlg, (HMENU)-1, ghInst, NULL );
if( !_hwndGrip ) { bStatus DBGCHK = FALSE; }
//
// Set the dialog icon.
//
INT cxIcon = GetSystemMetrics(SM_CXICON); INT cyIcon = GetSystemMetrics(SM_CYICON); HANDLE hIcon;
if( hIcon = LoadImage( ghInst, MAKEINTRESOURCE(IDI_PRINTER), IMAGE_ICON, cxIcon, cyIcon, 0 ) ) { SendMessage( _hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon ); }
//
// The small icon size is already cached for the queue view.
//
if( hIcon = LoadImage( ghInst, MAKEINTRESOURCE(IDI_PRINTER), IMAGE_ICON, gcxSmIcon, gcySmIcon, 0 ) ) { SendMessage( _hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon ); }
return bStatus; }
BOOL TRunDllDisplay:: bHandle_WM_SIZE( IN WPARAM wParam, IN LPARAM lParam ) { INT width = LOWORD( lParam ); INT height = HIWORD( lParam );
//
// Get the current window size.
//
RECT rect; GetWindowRect(_hDlg, &rect);
//
// Calculate the deltas in the x and y positions that we need to move
// each of the child controls.
//
INT dx = (rect.right - rect.left) - _ptLastSize.x; INT dy = (rect.bottom - rect.top) - _ptLastSize.y;
//
// Update the new size.
//
_ptLastSize.x = rect.right - rect.left; _ptLastSize.y = rect.bottom - rect.top;
//
// Set the sizing grip to the correct location.
//
if( _hwndGrip ) { SetWindowPos( _hwndGrip, NULL, width - _cxGrip, height - _cyGrip, _cxGrip, _cyGrip, SWP_NOZORDER | SWP_NOACTIVATE ); }
//
// Move the ok button.
//
GetWindowRect(GetDlgItem(_hDlg, IDOK), &rect);
MapWindowPoints(NULL, _hDlg, (LPPOINT)&rect, 2);
SetWindowPos(GetDlgItem(_hDlg, IDOK), NULL, rect.left+dx, rect.top+dy, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
//
// Resize the edit control
//
GetWindowRect(GetDlgItem(_hDlg, IDC_RUNDLL_TEXT), &rect);
MapWindowPoints(NULL, _hDlg, (LPPOINT)&rect, 2);
SetWindowPos(GetDlgItem(_hDlg, IDC_RUNDLL_TEXT), NULL, 0, 0, (rect.right-rect.left)+dx, (rect.bottom-rect.top)+dy, SWP_NOZORDER|SWP_NOMOVE);
return FALSE; }
BOOL TRunDllDisplay:: bHandle_WM_GETMINMAXINFO( IN WPARAM wParam, IN LPARAM lParam ) { BOOL bRetval = TRUE; LPMINMAXINFO pmmi = (LPMINMAXINFO)lParam;
if( ( _ptMinTrack.x != 0 ) || ( _ptMinTrack.y != 0 ) ) { pmmi->ptMinTrackSize = _ptMinTrack; bRetval = FALSE; }
return bRetval; }
BOOL TRunDllDisplay:: bHandleMessage( IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ) { BOOL bStatus = TRUE;
switch (uMsg) { case WM_INITDIALOG: bSetUI(); break;
case WM_SIZE: bStatus = bHandle_WM_SIZE( wParam, lParam ); break;
case WM_GETMINMAXINFO: bStatus = bHandle_WM_GETMINMAXINFO( wParam, lParam ); break;
case WM_COMMAND: switch ( LOWORD( wParam ) ) { case IDOK: case IDCANCEL: EndDialog( _hDlg, LOWORD( wParam ) ); break;
default: bStatus = FALSE; break; }
default: bStatus = FALSE; break; } return bStatus; }
/********************************************************************
Very simple file output class
********************************************************************/
TFile:: TFile( IN LPCTSTR pszFileName, IN BOOL bNoUnicodeByteMark ) : _strFileName( pszFileName ), _hFile( INVALID_HANDLE_VALUE ), _bValid( FALSE ) { if( !_strFileName.bEmpty() ) { _hFile = CreateFile( _strFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( _hFile != INVALID_HANDLE_VALUE ) { _bValid = TRUE; }
//
// If we are built for unicode then write the unicode byte mark.
//
#ifdef UNICODE
if( _bValid && !bNoUnicodeByteMark ) { WORD wUnicodeByteMark = kUnicodePrefix; _bValid = bWrite( sizeof( wUnicodeByteMark ), reinterpret_cast<LPBYTE>( &wUnicodeByteMark ) ); } #endif
} }
TFile:: ~TFile( VOID ) { if( _hFile != INVALID_HANDLE_VALUE ) { CloseHandle( _hFile ); } }
BOOL TFile:: bValid( VOID ) { return _bValid; }
BOOL TFile:: bWrite( IN TString &strString, OUT UINT *pBytesWritten OPTIONAL ) { return bWrite( strString.uLen() * sizeof( TCHAR ), reinterpret_cast<LPBYTE>( const_cast<LPTSTR>( static_cast<LPCTSTR>( strString ) ) ), pBytesWritten ); }
BOOL TFile:: bWrite( IN UINT uSize, IN LPBYTE pData, OUT UINT *pBytesWritten OPTIONAL ) { DWORD dwWritten; TStatusB bStatus;
bStatus DBGCHK = WriteFile(_hFile, pData, uSize, &dwWritten, NULL ); if( bStatus ) { if( pBytesWritten ) { *pBytesWritten = dwWritten; }
bStatus DBGCHK = dwWritten == uSize ? TRUE : FALSE; }
return bStatus;
}
|